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"
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
35ExprDialog::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
141 _currentEditorIdx = idx;
142 showEditorTimer->setSingleShot(true);
143 showEditorTimer->start();
144}
145
147
149 // populate the expressions
152 QDialog::show();
153}
154
156 // populate the expressions
159 return QDialog::exec();
160}
161
162void ExprDialog::keyPressEvent(QKeyEvent* event) {
163 if (event->key() == Qt::Key_Escape) return;
164 return QDialog::keyPressEvent(event);
165}
166
167void ExprDialog::closeEvent(QCloseEvent* event) {
168 emit dialogClosed();
169 QDialog::closeEvent(event);
170}
171
173 emit dialogClosed();
174 QDialog::reject();
175}
176
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
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
215void 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
265void 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
277void ExprDialog::findPrevInHelp() { findHelper(QTextDocument::FindBackward); }
278
283
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
334 editor->setExpr("", false);
335 grapher->expr.setExpr("");
336 grapher->update();
337}
void setExpr(const std::string &str)
bool getExpressionDirs()
void clearSelection()
void findPrevInHelp()
QLineEdit * helpFindBox
Definition ExprDialog.h:60
void setupHelp(QTabWidget *tab)
QString prevFind
Definition ExprDialog.h:64
void expressionApplied()
QPushButton * saveAsButton
Definition ExprDialog.h:58
int _currentEditorIdx
Definition ExprDialog.h:65
QPushButton * previewButton
Definition ExprDialog.h:58
QPushButton * saveButton
Definition ExprDialog.h:58
void reject()
void findNextInHelp()
void preview()
void verifiedApply()
ExprDialog(QWidget *parent)
QTimer * showEditorTimer
Definition ExprDialog.h:61
ExprGrapherWidget * grapher
Definition ExprDialog.h:52
void applyExpression()
void closeEvent(QCloseEvent *event)
QPushButton * acceptButton
Definition ExprDialog.h:54
void keyPressEvent(QKeyEvent *event)
ExprControlCollection * controls
Definition ExprDialog.h:56
QPushButton * cancelButton
Definition ExprDialog.h:55
QLabel * previewCommentLabel
Definition ExprDialog.h:53
void verifiedAccept()
QPushButton * clearButton
Definition ExprDialog.h:59
void previewExpression()
void showEditor(int idx)
QPushButton * applyButton
Definition ExprDialog.h:58
void _showEditor()
QPushButton * saveLocalButton
Definition ExprDialog.h:59
void dialogClosed()
ExprBrowser * browser
Definition ExprDialog.h:49
void findHelper(QTextDocument::FindFlags flags)
void clearExpression()
QTextBrowser * helpBrowser
Definition ExprDialog.h:62
BasicExpression expr
bool isValid() const
Definition Expression.h:133
const std::vector< Error > & getErrors() const
Definition Expression.h:144