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