Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
baseWidget.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49
50 //== INCLUDES =================================================================
51 #include <QVBoxLayout>
52 #include <QPushButton>
53 #include <QDialog>
54 #include <QTextEdit>
55 #include <QFileDialog>
56 #include <QMenu>
57 #include <QMenuBar>
58 #include <QMessageBox>
59
60 #include <QApplication>
61 #include <QClipboard>
62 #include <QScriptEngine>
63
64 #include <QDomDocument>
65
66 #include <QXmlQuery>
67 #include <QXmlResultItems>
68
69 #include <OpenFlipper/common/GlobalOptions.hh>
70
71 #include "baseWidget.hh"
72 #include "toolBoxElement.hh"
73 #include "scene/sceneElement.hh"
74
75 #include "parser/context.hh"
76
77 //== NAMESPACES ===============================================================
78 namespace VSI {
79
80 //=============================================================================
81 //
82 // CLASS BaseWidget - IMPLEMENTATION
83 //
84 //=============================================================================
85
86 // static variable for singleton
87 BaseWidget * BaseWidget::base_ = NULL;
88
89 //------------------------------------------------------------------------------
90
91 // Constructor
92 BaseWidget::BaseWidget (Context *_ctx, QWidget *_parent) :
93 QMainWindow (_parent),
94 ctx_ (_ctx),
95 fileName_ (),
96 changedContent_ (false)
97 {
98 setWindowIcon (OpenFlipper::Options::OpenFlipperIcon ());
99 updateTitle ();
100
101 splitter_ = new QSplitter (Qt::Horizontal, this);
102 toolbox_ = new QToolBox ();
103 views_ = new QStackedWidget ();
104
105
106 toolbox_->setMinimumWidth (275);
107
108 QVBoxLayout *layout = new QVBoxLayout;
109
110 layout->addWidget (toolbox_);
111
112 QPushButton *execute = new QPushButton ("Execute");
113 layout->addWidget (execute);
114
115 QWidget *w = new QWidget;
116 w->setLayout (layout);
117
118 mainScene_ = new GraphicsScene (_ctx);
119 views_->addWidget(mainScene_->graphicsView ());
120
121 splitter_->addWidget (w);
122 splitter_->addWidget (views_);
123 QList<int> sizes;
124 sizes << 275 << 10000;
125 splitter_->setSizes (sizes);
126
127 setCentralWidget (splitter_);
128
129 resize (1000, 700);
130
131 setupUi ();
132
133 connect (execute, SIGNAL (clicked (bool)), this, SLOT (executeCode ()));
134
135 connect (mainScene_, SIGNAL (contentChanged()), this, SLOT (contentChanged()));
136
137
138 QMenu *menu = new QMenu (tr("&File"));
139 QIcon icon;
140
141 icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"add-empty-object.png");
142 menu->addAction (icon, tr("New"), this, SLOT (newFile()), QKeySequence::New);
143
144 icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"document-open.png");
145 menu->addAction (icon, tr("Open ..."), this, SLOT (load()), QKeySequence::Open);
146
147 menu->addSeparator ();
148
149 icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"document-save.png");
150 menu->addAction (icon, tr("Save"), this, SLOT (save()), QKeySequence::Save);
151
152 icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"document-save-as.png");
153 menu->addAction (icon, tr("Save as ..."), this, SLOT (saveAs()), QKeySequence::SaveAs);
154 menu->addSeparator ();
155
156 icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"window-close.png");
157 menu->addAction (icon, tr("Close"), this, SLOT (close()), QKeySequence::Close);
158
159 menuBar()->addMenu (menu);
160
161 menu = new QMenu (tr("&Script"));
162 icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"scriptEditor.png");
163 menu->addAction (icon, tr("Open in script editor"), this, SLOT (codeToScript()));
164
165 menuBar()->addMenu (menu);
166
167 base_ = this;
168 }
169
170 //------------------------------------------------------------------------------
171
173 BaseWidget::~BaseWidget ()
174 {
175 base_ = NULL;
176 }
177
178 //------------------------------------------------------------------------------
179
181 void BaseWidget::setupUi ()
182 {
183
184 foreach (const QString &c, ctx_->categories ())
185 {
186 QWidget *widget = new QWidget (toolbox_);
187 QVBoxLayout *layout = new QVBoxLayout ();
188 foreach (Element *e, ctx_->elements (c))
189 {
190 if (!(e->flags () & ELEMENT_FLAG_SKIP_TOOLBOX))
191 {
192 ToolBoxElement *t = new ToolBoxElement (e, widget);
193 layout->addWidget (t);
194 }
195 }
196 layout->addStretch ();
197 widget->setLayout (layout);
198 toolbox_->addItem (widget, c);
199 }
200 }
201
202 //------------------------------------------------------------------------------
203
205 void BaseWidget::executeCode ()
206 {
207 QString errors = "";
208
209 QString code = mainScene_->generateCode (errors);
210
211 if (errors.isEmpty ())
212 {
213 ctx_->scriptEngine ()->pushContext ();
214 ctx_->scriptEngine ()->evaluate (code);
215 ctx_->scriptEngine ()->popContext ();
216 return;
217 }
218
219 errors = "<h3> " + tr("Following Elements could not be processed:") + "</h3>" + errors;
220
221 QMessageBox::warning (this, tr("Error during code generation"), errors,
222 QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
223 }
224
225 //------------------------------------------------------------------------------
226
228 void BaseWidget::codeToScript()
229 {
230
231 QString errors = "";
232
233 QString code = mainScene_->generateCode (errors);
234
235 if (errors.isEmpty ())
236 {
237 emit codeToScriptEditor (code);
238 return;
239 }
240
241 errors = "<qt> " + tr("Following Elements could not be processed:") + errors + "</qt>";
242
243 QMessageBox::warning (this, tr("Error during code generation"), errors,
244 QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
245 }
246
247 //------------------------------------------------------------------------------
248
250 bool BaseWidget::saveAs()
251 {
252 return save (true);
253 }
254
255 //------------------------------------------------------------------------------
256
258 void VSI::BaseWidget::load()
259 {
260 if (!saveIfChanged ())
261 return;
262
263 QString filename = QFileDialog::getOpenFileName (this,
264 tr("Load Visual Script"),
265 OpenFlipperSettings().value("Core/CurrentDir").toString(),
266 tr("Visual Script File (*.ofvs)"));
267
268 if (filename.isEmpty ())
269 return;
270
271 // Get the chosen directory and remember it.
272 QFileInfo fileInfo(filename);
273 OpenFlipperSettings().setValue("Core/CurrentDir", fileInfo.absolutePath() );
274
275 QFile f (filename);
276 if (!f.open (QFile::ReadOnly))
277 {
278 QMessageBox msgBox;
279 msgBox.setText(tr("Unable to open file."));
280 msgBox.setInformativeText(filename);
281 msgBox.exec();
282 return;
283 }
284
285 while (!scenes_.isEmpty())
286 scenes_.pop ();
287 views_->setCurrentWidget (mainScene_->graphicsView());
288
289 QXmlQuery query;
290 query.setFocus (&f);
291
292 query.setQuery ("VisualScript");
293
294 QXmlResultItems root;
295
296 if (query.isValid ())
297 {
298 query.evaluateTo (&root);
299
300 QXmlItem item (root.next ());
301 if (!item.isNull ())
302 {
303 QXmlQuery q (query);
304 q.setFocus (item);
305 mainScene_->loadFromXml (q);
306 }
307 }
308
309 changedContent_ = false;
310 fileName_ = filename;
311 updateTitle ();
312 }
313
314 //------------------------------------------------------------------------------
315
317 bool BaseWidget::save(bool _newName)
318 {
319
320 QString filename;
321
322 if (fileName_.isEmpty () || _newName)
323 {
324 QFileDialog *d = new QFileDialog (this, tr("Save Visual Script"),
325 OpenFlipperSettings().value("Core/CurrentDir").toString(),
326 tr("Visual Script File (*.ofvs)"));
327
328 d->setAcceptMode (QFileDialog::AcceptSave);
329 d->setDefaultSuffix ("ofvs");
330
331 if (QDialog::Accepted == d->exec ())
332 filename = d->selectedFiles ()[0];
333 }
334 else
335 filename = fileName_;
336
337 if (filename.isEmpty ())
338 return false;
339
340 // Get the chosen directory and remember it.
341 QFileInfo fileInfo(filename);
342 OpenFlipperSettings().setValue("Core/CurrentDir", fileInfo.absolutePath() );
343
344 QFile f (filename);
345 if (!f.open (QFile::WriteOnly))
346 {
347 QMessageBox msgBox;
348 msgBox.setText(tr("Unable to write file."));
349 msgBox.setInformativeText(filename);
350 msgBox.exec();
351 return false;
352 }
353
354 QDomDocument doc("VisualScript");
355 QDomElement root = doc.createElement("VisualScript");
356 doc.appendChild(root);
357
358 mainScene_->saveToXml (doc, root);
359
360 f.write (doc.toString().toUtf8 ());
361 f.close ();
362
363 changedContent_ = false;
364 fileName_ = filename;
365 updateTitle ();
366
367 return true;
368 }
369
370 //------------------------------------------------------------------------------
371
373 void BaseWidget::newFile()
374 {
375 if (!saveIfChanged ())
376 return;
377
378 while (!scenes_.isEmpty())
379 scenes_.pop ();
380 views_->setCurrentWidget (mainScene_->graphicsView());
381
382 fileName_ = QString ();
383 mainScene_->clearScene ();
384 changedContent_ = false;
385 updateTitle ();
386 }
387
388 //------------------------------------------------------------------------------
389
391 void BaseWidget::updateTitle()
392 {
393 if (fileName_.isEmpty ())
394 setWindowTitle (tr("Untitled") + (changedContent_ ? " [" + tr("Modified") + "] " : "") + " - Visual Script Editor");
395 else
396 setWindowTitle (fileName_ + (changedContent_ ? " [" + tr("Modified") + "] " : "") + " - Visual Script Editor");
397 }
398
399 //------------------------------------------------------------------------------
400
402 void BaseWidget::contentChanged()
403 {
404 if (!changedContent_)
405 {
406 changedContent_ = true;
407 updateTitle ();
408 }
409 }
410
411 //------------------------------------------------------------------------------
412
414 bool BaseWidget::saveIfChanged()
415 {
416 if (changedContent_)
417 {
418 QMessageBox msgBox;
419 msgBox.setText(tr("The visual script has been modified."));
420 msgBox.setInformativeText(tr("Do you want to save your changes?"));
421 msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
422 msgBox.setDefaultButton(QMessageBox::Save);
423 int ret = msgBox.exec();
424 switch (ret) {
425 case QMessageBox::Save:
426 // Save was clicked
427 if (!save ())
428 return false;
429 break;
430 case QMessageBox::Discard:
431 // Don't Save was clicked
432 break;
433 case QMessageBox::Cancel:
434 // Cancel was clicked
435 return false;
436 break;
437 default:
438 // should never be reached
439 break;
440 }
441 return true;
442 }
443 else
444 return true;
445 }
446
447 //------------------------------------------------------------------------------
448
450 void BaseWidget::closeEvent(QCloseEvent *_event)
451 {
452 if (!saveIfChanged ())
453 _event->ignore ();
454 else
455 _event->accept();
456 }
457
458 //------------------------------------------------------------------------------
459
461 BaseWidget * BaseWidget::createBaseWidget (Context *_ctx, QWidget *_parent)
462 {
463 if (!base_)
464 base_ = new BaseWidget (_ctx, _parent);
465 return base_;
466 }
467
468 //------------------------------------------------------------------------------
469
471 BaseWidget * BaseWidget::getBaseWidget()
472 {
473 return base_;
474 }
475
476 //------------------------------------------------------------------------------
477
479 void VSI::BaseWidget::pushScene(GraphicsScene * _scene)
480 {
481 scenes_.push (_scene);
482 views_->setCurrentWidget (_scene->graphicsView());
483 }
484
485 //------------------------------------------------------------------------------
486
488 void VSI::BaseWidget::popScene()
489 {
490 if (!scenes_.isEmpty())
491 scenes_.pop ();
492
493 if (!scenes_.isEmpty())
494 views_->setCurrentWidget (scenes_.top ()->graphicsView());
495 else
496 views_->setCurrentWidget (mainScene_->graphicsView());
497 }
498
499 //------------------------------------------------------------------------------
500
502 void VSI::BaseWidget::addScene(GraphicsScene * _scene)
503 {
504 views_->addWidget (_scene->graphicsView ());
505 }
506
507 //------------------------------------------------------------------------------
508
510 void VSI::BaseWidget::removeScene(GraphicsScene * _scene)
511 {
512 views_->removeWidget (_scene->graphicsView ());
513 }
514
515 //------------------------------------------------------------------------------
516 }
517
OpenFlipperSettings
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
Definition: GlobalOptions.cc:938
VSI
Definition: baseWidget.cc:78
VSI::BaseWidget::updateTitle
void updateTitle()
Update window title.
Definition: baseWidget.cc:391
VSI::BaseWidget
Definition: baseWidget.hh:75
VSI::Context
Definition: context.hh:76
VSI::ToolBoxElement
Definition: toolBoxElement.hh:67
VSI::BaseWidget::newFile
void newFile()
new empty file
Definition: baseWidget.cc:373
VSI::GraphicsScene::loadFromXml
void loadFromXml(QXmlQuery &_xml)
Load from xml.
Definition: graphicsScene.cc:889
VSI::BaseWidget::saveIfChanged
bool saveIfChanged()
Asks the user if he want to save his changes.
Definition: baseWidget.cc:414
VSI::BaseWidget::getBaseWidget
static BaseWidget * getBaseWidget()
Returns singleton.
Definition: baseWidget.cc:471
VSI::GraphicsScene::clearScene
void clearScene(bool _start=false)
clear the whole scene (_start = keep start element)
Definition: graphicsScene.cc:1042
VSI::BaseWidget::contentChanged
void contentChanged()
used changed something
Definition: baseWidget.cc:402
VSI::BaseWidget::addScene
void addScene(GraphicsScene *_scene)
add a new scene
Definition: baseWidget.cc:502
VSI::BaseWidget::load
void load()
load file
Definition: baseWidget.cc:258
VSI::GraphicsScene
Definition: graphicsScene.hh:86
VSI::Element
Definition: element.hh:74
VSI::GraphicsScene::saveToXml
void saveToXml(QDomDocument &_doc, QDomElement &_root)
Save to xml.
Definition: graphicsScene.cc:857
VSI::BaseWidget::createBaseWidget
static BaseWidget * createBaseWidget(Context *_ctx, QWidget *_parent=NULL)
Singleton constructor.
Definition: baseWidget.cc:461
GlobalOptions.hh
VSI::Element::flags
unsigned int flags() const
Flags.
Definition: element.hh:115
VSI::BaseWidget::closeEvent
void closeEvent(QCloseEvent *_event)
Chatch close event.
Definition: baseWidget.cc:450
VSI::GraphicsScene::graphicsView
GraphicsView * graphicsView()
Graphics view of the scene.
Definition: graphicsScene.hh:99
VSI::BaseWidget::pushScene
void pushScene(GraphicsScene *_scene)
show a new scene (function) in editor
Definition: baseWidget.cc:479
OpenFlipperQSettings::setValue
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
Definition: OpenFlipperQSettings.cc:68
VSI::BaseWidget::save
bool save(bool _newName=false)
save to file
Definition: baseWidget.cc:317
VSI::BaseWidget::removeScene
void removeScene(GraphicsScene *_scene)
remove a scene
Definition: baseWidget.cc:510
VSI::BaseWidget::popScene
void popScene()
go back to last scene (function)
Definition: baseWidget.cc:488