SeExpr
ExprDialog.cpp
Go to the documentation of this file.
1 /*
2 * Copyright Disney Enterprises, Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License
6 * and the following modification to it: Section 6 Trademarks.
7 * deleted and replaced with:
8 *
9 * 6. Trademarks. This License does not grant permission to use the
10 * trade names, trademarks, service marks, or product names of the
11 * Licensor and its affiliates, except as required for reproducing
12 * the content of the NOTICE file.
13 *
14 * You may obtain a copy of the License at
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * @file ExprDialog.cpp
18 * @brief A basic editor/browser/previewer for expression editing
19 * @author jlacewel
20 */
21 
22 #include "ExprBrowser.h"
23 #include "ExprGrapher2d.h"
24 #include "ExprDialog.h"
25 #include "ExprControlCollection.h"
26 
27 #include <QDir>
28 #include <QApplication>
29 #include <QLabel>
30 #include <iostream>
31 #include <fstream>
32 
33 #define P3D_CONFIG_ENVVAR "P3D_CONFIG_PATH"
34 
35 ExprDialog::ExprDialog(QWidget* parent) : QDialog(parent), _currentEditorIdx(0) {
36  this->setMinimumWidth(600);
37  QVBoxLayout* rootLayout = new QVBoxLayout(0);
38  rootLayout->setMargin(2);
39  this->setLayout(rootLayout);
40 
41  showEditorTimer = new QTimer();
42  connect(showEditorTimer, SIGNAL(timeout()), SLOT(_showEditor()));
43 
44  QSplitter* vsplitter = new QSplitter(Qt::Vertical, this);
45  rootLayout->addWidget(vsplitter);
46 
47  QTabWidget* topTabWidget = new QTabWidget();
48  vsplitter->addWidget(topTabWidget);
49 
50  QWidget* previewLibraryWidget = new QWidget();
51  QHBoxLayout* previewLibraryLayout = new QHBoxLayout();
52  previewLibraryWidget->setLayout(previewLibraryLayout);
53  topTabWidget->addTab(previewLibraryWidget, "Preview / Library");
54 
55  QWidget* bottomWidget = new QWidget();
56  vsplitter->addWidget(bottomWidget);
57  QVBoxLayout* bottomLayout = new QVBoxLayout();
58  bottomLayout->setMargin(1);
59  bottomWidget->setLayout(bottomLayout);
60 
61  // setup preview
62  QWidget* leftWidget = new QWidget();
63  leftWidget->setFixedWidth(450);
64  QVBoxLayout* leftLayout = new QVBoxLayout();
65  leftLayout->setMargin(0);
66  leftWidget->setLayout(leftLayout);
67  QHBoxLayout* previewLayout = new QHBoxLayout();
68  grapher = new ExprGrapherWidget(this, 200, 200);
69  previewLayout->addWidget(grapher, 0);
70  previewCommentLabel = new QLabel();
71  previewLayout->addWidget(previewCommentLabel, 1, Qt::AlignLeft | Qt::AlignTop);
72  leftLayout->addLayout(previewLayout);
73  previewLibraryLayout->addWidget(leftWidget);
74 
75  // setup button bar
76  // QWidget* buttonBarWidget=new QWidget();
77  QHBoxLayout* buttonBarLayout = new QHBoxLayout();
78  // buttonBarWidget->setLayout(buttonBarLayout);
79  buttonBarLayout->setMargin(1);
80  previewButton = new QPushButton("Preview");
81  buttonBarLayout->addWidget(previewButton);
82  saveButton = new QPushButton("Save");
83  buttonBarLayout->addWidget(saveButton);
84  saveAsButton = new QPushButton("Save As");
85  buttonBarLayout->addWidget(saveAsButton);
86  saveLocalButton = new QPushButton("Save Local");
87  saveLocalButton->setEnabled(false);
88  buttonBarLayout->addWidget(saveLocalButton);
89  clearButton = new QPushButton("Clear");
90  buttonBarLayout->addWidget(clearButton);
91  bottomLayout->addLayout(buttonBarLayout);
92 
94 
95  // controls
96  QScrollArea* scrollArea = new QScrollArea();
97  scrollArea->setWidget(controls);
98  // scrollArea->setWidget(new QLabel("test\nweird\nfds\nfdsahsha\nfsdajdlsa\nfasdjjhsafd\nfasdhjdfsa\nfdasjdfsha"));
99  scrollArea->setFocusPolicy(Qt::NoFocus);
100  scrollArea->setMinimumHeight(100);
101  scrollArea->setFixedWidth(450);
102  scrollArea->setWidgetResizable(true);
103  leftLayout->addWidget(scrollArea, 1);
104 
105  // make button bar
106  editor = new ExprEditor(this, controls);
107  connect(editor, SIGNAL(apply()), SLOT(verifiedApply()));
108  connect(editor, SIGNAL(preview()), SLOT(previewExpression()));
109  connect(grapher, SIGNAL(preview()), SLOT(previewExpression()));
110  bottomLayout->addWidget(editor);
111 
112  // make expression library browser
113  browser = new ExprBrowser(0, editor);
114  previewLibraryLayout->addWidget(browser);
115 
116  // dialog buttons
117  QHBoxLayout* buttonLayout = new QHBoxLayout(0);
118  buttonLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum));
119  applyButton = new QPushButton("Apply");
120  buttonLayout->addWidget(applyButton);
121  acceptButton = new QPushButton("Accept");
122  buttonLayout->addWidget(acceptButton);
123  cancelButton = new QPushButton("Cancel");
124  buttonLayout->addWidget(cancelButton);
125  connect(applyButton, SIGNAL(clicked()), this, SLOT(verifiedApply()));
126  connect(acceptButton, SIGNAL(clicked()), this, SLOT(verifiedAccept()));
127  connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
128  rootLayout->addLayout(buttonLayout);
129 
130  setupHelp(topTabWidget);
131 
132  // connect buttons
133  connect(previewButton, SIGNAL(clicked()), SLOT(previewExpression()));
134  connect(clearButton, SIGNAL(clicked()), SLOT(clearExpression()));
135  connect(saveButton, SIGNAL(clicked()), browser, SLOT(saveExpression()));
136  connect(saveAsButton, SIGNAL(clicked()), browser, SLOT(saveExpressionAs()));
137  connect(saveLocalButton, SIGNAL(clicked()), browser, SLOT(saveLocalExpressionAs()));
138 }
139 
140 void ExprDialog::showEditor(int idx) {
141  _currentEditorIdx = idx;
142  showEditorTimer->setSingleShot(true);
143  showEditorTimer->start();
144 }
145 
147 
149  // populate the expressions
151  browser->expandAll();
152  QDialog::show();
153 }
154 
156  // populate the expressions
158  browser->expandAll();
159  return QDialog::exec();
160 }
161 
162 void ExprDialog::keyPressEvent(QKeyEvent* event) {
163  if (event->key() == Qt::Key_Escape) return;
164  return QDialog::keyPressEvent(event);
165 }
166 
167 void ExprDialog::closeEvent(QCloseEvent* event) {
168  emit dialogClosed();
169  QDialog::closeEvent(event);
170 }
171 
173  emit dialogClosed();
174  QDialog::reject();
175 }
176 
178  applyExpression();
179  if (grapher->expr.isValid()) {
180  emit expressionApplied();
181  } else {
182  QMessageBox msgBox;
183  msgBox.setText("Your expression had possible errors.");
184  msgBox.setInformativeText("Do you want to accept your expression anyways?");
185  QPushButton* okButton = msgBox.addButton("OK", QMessageBox::RejectRole);
186  msgBox.addButton("Cancel", QMessageBox::AcceptRole);
187  int ret = msgBox.exec();
188  Q_UNUSED(ret);
189  if (msgBox.clickedButton() == okButton) emit expressionApplied();
190  }
191 }
192 
194  applyExpression();
195  if (grapher->expr.isValid()) {
196  emit expressionApplied();
197  emit dialogClosed();
198  accept();
199  } else {
200  QMessageBox msgBox;
201  msgBox.setText("Your expression had possible errors.");
202  msgBox.setInformativeText("Do you want to accept your expression anyways?");
203  QPushButton* okButton = msgBox.addButton("OK", QMessageBox::RejectRole);
204  msgBox.addButton("Cancel", QMessageBox::AcceptRole);
205  int ret = msgBox.exec();
206  Q_UNUSED(ret);
207  if (msgBox.clickedButton() == okButton) {
208  emit expressionApplied();
209  emit dialogClosed();
210  accept();
211  }
212  }
213 }
214 
215 void ExprDialog::setupHelp(QTabWidget* tab) {
216  QWidget* browserspace = new QWidget(tab);
217  helpBrowser = new QTextBrowser(browserspace);
218  tab->addTab(browserspace, "Help");
219 
220  // Locate help docs relative to location of the app itself
221  QFile* helpDoc = new QFile(QCoreApplication::applicationDirPath() + "/../share/doc/SeExpr2/SeExpressions.html");
222  if (helpDoc->exists()) {
223  QString sheet =
224  "body {background-color: #eeeeee; color: #000000;} \na {color: #3333ff; text-decoration: none;}\n";
225  helpBrowser->document()->setDefaultStyleSheet(sheet);
226  helpBrowser->setSource(helpDoc->fileName());
227  }
228 
229  QPushButton* backPb = new QPushButton("Back");
230  // backPb->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowLeft));
231  backPb->setEnabled(false);
232  QPushButton* forwardPb = new QPushButton("Forward");
233  // forwardPb->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowRight));
234  forwardPb->setEnabled(false);
235 
236  QVBoxLayout* helpLayout = new QVBoxLayout(browserspace);
237  QHBoxLayout* helpPbLayout = new QHBoxLayout;
238  helpLayout->addLayout(helpPbLayout);
239  helpPbLayout->addWidget(backPb);
240  helpPbLayout->addWidget(forwardPb);
241  // helpPbLayout->addItem(new QSpacerItem(0,0, QSizePolicy::MinimumExpanding,
242  // QSizePolicy::Minimum));
243  QHBoxLayout* findBar = new QHBoxLayout();
244  helpPbLayout->addWidget(new QLabel("Find"), /*stretch*/ false);
245  helpFindBox = new QLineEdit;
246  helpPbLayout->addWidget(helpFindBox, /*stretch*/ false);
247  connect(helpFindBox, SIGNAL(returnPressed()), this, SLOT(findNextInHelp()));
248  QPushButton* nextButton = new QPushButton("Find Next");
249  QPushButton* prevButton = new QPushButton("Find Prev");
250  helpPbLayout->addWidget(nextButton, /*stretch*/ false);
251  helpPbLayout->addWidget(prevButton, /*stretch*/ false);
252  connect(nextButton, SIGNAL(clicked()), this, SLOT(findNextInHelp()));
253  connect(prevButton, SIGNAL(clicked()), this, SLOT(findPrevInHelp()));
254  helpPbLayout->addLayout(findBar, /*stretch*/ false);
255  helpLayout->addWidget(helpBrowser, /*stretch*/ true);
256  helpBrowser->setMinimumHeight(120);
257 
258  // wire up help browser forward/back buttons
259  connect(backPb, SIGNAL(clicked()), helpBrowser, SLOT(backward()));
260  connect(forwardPb, SIGNAL(clicked()), helpBrowser, SLOT(forward()));
261  connect(helpBrowser, SIGNAL(backwardAvailable(bool)), backPb, SLOT(setEnabled(bool)));
262  connect(helpBrowser, SIGNAL(forwardAvailable(bool)), forwardPb, SLOT(setEnabled(bool)));
263 }
264 
265 void ExprDialog::findHelper(QTextDocument::FindFlags flags) {
266  QTextDocument* doc = helpBrowser->document();
267  if (prevFind != helpFindBox->text()) {
268  prevFind = helpFindBox->text();
269  helpBrowser->setTextCursor(QTextCursor(doc));
270  }
271  QTextCursor blah = doc->find(helpFindBox->text(), helpBrowser->textCursor(), flags);
272  helpBrowser->setTextCursor(blah);
273 }
274 
276 
277 void ExprDialog::findPrevInHelp() { findHelper(QTextDocument::FindBackward); }
278 
280  applyExpression();
281  emit preview();
282 }
283 
285  editor->clearErrors();
286  // set new expression
288  grapher->update();
289 
290  // set the label widget to mention that variables will not be previewed
291  bool empty = true;
292  if (grapher->expr.varmap.size() > 0) {
293  std::stringstream s;
294  s << "<b>Variables not supported in preview (assumed zero):</b><br>";
295  int count = 0;
296  for (BasicExpression::VARMAP::iterator i = grapher->expr.varmap.begin(); i != grapher->expr.varmap.end(); ++i) {
297  count++;
298  s << "$" << i->first << " ";
299  if (count % 4 == 0) s << "<br>";
300  }
301  previewCommentLabel->setText(s.str().c_str());
302  empty = false;
303  } else
304  previewCommentLabel->setText("");
305  // set the label widget to mention that variables will not be previewed
306  if (grapher->expr.funcmap.size() > 0) {
307  std::stringstream s;
308  s << "<b>Functions not supported in preview (assumed zero):</b><br>";
309  int count = 0;
310  for (BasicExpression::FUNCMAP::iterator i = grapher->expr.funcmap.begin(); i != grapher->expr.funcmap.end();
311  ++i) {
312  count++;
313  s << "" << i->first << "() ";
314  if (count % 4 == 0) s << "<br>";
315  }
316  previewCommentLabel->setText(s.str().c_str());
317  empty = false;
318  }
319  if (empty) previewCommentLabel->setText("");
320 
321  // put errors into editor module
322  bool valid = grapher->expr.isValid();
323  if (!valid) {
324  const std::vector<SeExpr2::Expression::Error>& errors = grapher->expr.getErrors();
325  for (unsigned int i = 0; i < errors.size(); i++) {
326  editor->addError(errors[i].startPos, errors[i].endPos, errors[i].error);
327  }
328  editor->nextError();
329  }
330 }
331 
334  editor->setExpr("", false);
335  grapher->expr.setExpr("");
336  grapher->update();
337 }
ExprGrapherWidget::expr
BasicExpression expr
Definition: ExprGrapher2d.h:75
ExprEditor::clearErrors
void clearErrors()
Definition: ExprEditor.cpp:411
ExprBrowser::clearSelection
void clearSelection()
Definition: ExprBrowser.cpp:327
SeExpr2::Expression::isValid
bool isValid() const
Definition: Expression.h:133
SeExpr2::Expression::getErrors
const std::vector< Error > & getErrors() const
Definition: Expression.h:144
ExprDialog::setupHelp
void setupHelp(QTabWidget *tab)
Definition: ExprDialog.cpp:215
ExprDialog::show
void show()
Definition: ExprDialog.cpp:148
BasicExpression::setExpr
void setExpr(const std::string &str)
Definition: BasicExpression.cpp:40
ExprEditor
Definition: ExprEditor.h:94
ExprDialog::exec
int exec()
Definition: ExprDialog.cpp:155
ExprDialog::dialogClosed
void dialogClosed()
ExprBrowser::expandAll
void expandAll()
Definition: ExprBrowser.cpp:394
ExprBrowser
Definition: ExprBrowser.h:43
ExprDialog::saveAsButton
QPushButton * saveAsButton
Definition: ExprDialog.h:58
ExprGrapherWidget
Definition: ExprGrapher2d.h:69
ExprDialog::editor
ExprEditor * editor
Definition: ExprDialog.h:48
ExprDialog.h
ExprDialog::grapher
ExprGrapherWidget * grapher
Definition: ExprDialog.h:52
ExprDialog::findHelper
void findHelper(QTextDocument::FindFlags flags)
Definition: ExprDialog.cpp:265
ExprDialog::ExprDialog
ExprDialog(QWidget *parent)
Definition: ExprDialog.cpp:35
ExprDialog::applyButton
QPushButton * applyButton
Definition: ExprDialog.h:58
ExprEditor::nextError
void nextError()
Definition: ExprEditor.cpp:405
ExprGrapherWidget::update
void update()
Definition: ExprGrapher2d.cpp:79
ExprControlCollection::showEditor
void showEditor(int idx)
Definition: ExprControlCollection.cpp:413
ExprDialog::helpBrowser
QTextBrowser * helpBrowser
Definition: ExprDialog.h:62
ExprDialog::clearButton
QPushButton * clearButton
Definition: ExprDialog.h:59
ExprDialog::prevFind
QString prevFind
Definition: ExprDialog.h:64
ExprDialog::acceptButton
QPushButton * acceptButton
Definition: ExprDialog.h:54
ExprDialog::controls
ExprControlCollection * controls
Definition: ExprDialog.h:56
ExprControlCollection
Definition: ExprControlCollection.h:81
ExprDialog::clearExpression
void clearExpression()
Definition: ExprDialog.cpp:332
ExprDialog::previewExpression
void previewExpression()
Definition: ExprDialog.cpp:279
ExprDialog::closeEvent
void closeEvent(QCloseEvent *event)
Definition: ExprDialog.cpp:167
ExprDialog::verifiedApply
void verifiedApply()
Definition: ExprDialog.cpp:177
ExprDialog::previewCommentLabel
QLabel * previewCommentLabel
Definition: ExprDialog.h:53
BasicExpression::varmap
VARMAP varmap
Definition: BasicExpression.h:80
ExprEditor::addError
void addError(const int startPos, const int endPos, const std::string &error)
Definition: ExprEditor.cpp:388
ExprDialog::showEditor
void showEditor(int idx)
Definition: ExprDialog.cpp:140
ExprDialog::findPrevInHelp
void findPrevInHelp()
Definition: ExprDialog.cpp:277
ExprEditor::getExpr
std::string getExpr()
Definition: ExprEditor.cpp:373
ExprDialog::cancelButton
QPushButton * cancelButton
Definition: ExprDialog.h:55
ExprDialog::findNextInHelp
void findNextInHelp()
Definition: ExprDialog.cpp:275
ExprBrowser.h
ExprDialog::previewButton
QPushButton * previewButton
Definition: ExprDialog.h:58
ExprDialog::preview
void preview()
ExprEditor::setExpr
void setExpr(const std::string &expression, const bool apply=false)
Definition: ExprEditor.cpp:375
ExprDialog::verifiedAccept
void verifiedAccept()
Definition: ExprDialog.cpp:193
ExprDialog::applyExpression
void applyExpression()
Definition: ExprDialog.cpp:284
ExprGrapher2d.h
ExprDialog::_currentEditorIdx
int _currentEditorIdx
Definition: ExprDialog.h:65
ExprDialog::showEditorTimer
QTimer * showEditorTimer
Definition: ExprDialog.h:61
ExprBrowser::getExpressionDirs
bool getExpressionDirs()
Definition: ExprBrowser.cpp:415
ExprDialog::_showEditor
void _showEditor()
Definition: ExprDialog.cpp:146
ExprDialog::helpFindBox
QLineEdit * helpFindBox
Definition: ExprDialog.h:60
ExprDialog::saveButton
QPushButton * saveButton
Definition: ExprDialog.h:58
BasicExpression::funcmap
FUNCMAP funcmap
Definition: BasicExpression.h:82
ExprControlCollection.h
ExprDialog::keyPressEvent
void keyPressEvent(QKeyEvent *event)
Definition: ExprDialog.cpp:162
ExprDialog::expressionApplied
void expressionApplied()
ExprDialog::browser
ExprBrowser * browser
Definition: ExprDialog.h:49
ExprDialog::reject
void reject()
Definition: ExprDialog.cpp:172
ExprDialog::saveLocalButton
QPushButton * saveLocalButton
Definition: ExprDialog.h:59