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
93 controls = new ExprControlCollection();
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
146 void ExprDialog::_showEditor() { controls->showEditor(_currentEditorIdx); }
147
148 void ExprDialog::show() {
149 // populate the expressions
150 browser->getExpressionDirs();
151 browser->expandAll();
152 QDialog::show();
153 }
154
155 int ExprDialog::exec() {
156 // populate the expressions
157 browser->getExpressionDirs();
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
172 void ExprDialog::reject() {
173 emit dialogClosed();
174 QDialog::reject();
175 }
176
177 void ExprDialog::verifiedApply() {
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
193 void ExprDialog::verifiedAccept() {
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
275 void ExprDialog::findNextInHelp() { findHelper(0); }
276
277 void ExprDialog::findPrevInHelp() { findHelper(QTextDocument::FindBackward); }
278
279 void ExprDialog::previewExpression() {
280 applyExpression();
281 emit preview();
282 }
283
284 void ExprDialog::applyExpression() {
285 editor->clearErrors();
286 // set new expression
287 grapher->expr.setExpr(editor->getExpr());
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
332 void ExprDialog::clearExpression() {
333 browser->clearSelection();
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