diff options
author | Marius Kintel <marius@kintel.net> | 2013-05-28 05:25:03 (GMT) |
---|---|---|
committer | Marius Kintel <marius@kintel.net> | 2013-05-28 05:25:03 (GMT) |
commit | 33e873d8dae644b28dd3d6cbcf04450d6675fafd (patch) | |
tree | a0d6e570b21f18763ef33099b486d735ec22f2f4 /src/mainwin.cc | |
parent | eade7ede546f2415dfe6a8ff36a77136f883d03b (diff) |
Changed compile GUI logic to properly handler automatic reload on cascading changes
Diffstat (limited to 'src/mainwin.cc')
-rw-r--r-- | src/mainwin.cc | 237 |
1 files changed, 154 insertions, 83 deletions
diff --git a/src/mainwin.cc b/src/mainwin.cc index ac75269..52b432c 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -205,10 +205,16 @@ MainWindow::MainWindow(const QString &filename) connect(animate_timer, SIGNAL(timeout()), this, SLOT(updateTVal())); autoReloadTimer = new QTimer(this); - autoReloadTimer->setSingleShot(false); + autoReloadTimer->setSingleShot(true); + autoReloadTimer->setInterval(200); connect(autoReloadTimer, SIGNAL(timeout()), this, SLOT(checkAutoReload())); - connect(this->e_tval, SIGNAL(textChanged(QString)), this, SLOT(actionCompile())); + waitAfterReloadTimer = new QTimer(this); + waitAfterReloadTimer->setSingleShot(true); + waitAfterReloadTimer->setInterval(200); + connect(waitAfterReloadTimer, SIGNAL(timeout()), this, SLOT(waitAfterReload())); + + connect(this->e_tval, SIGNAL(textChanged(QString)), this, SLOT(actionRenderCSG())); connect(this->e_fps, SIGNAL(textChanged(QString)), this, SLOT(updatedFps())); animate_panel->hide(); @@ -288,8 +294,8 @@ MainWindow::MainWindow(const QString &filename) // Design menu connect(this->designActionAutoReload, SIGNAL(toggled(bool)), this, SLOT(autoReloadSet(bool))); - connect(this->designActionReloadAndCompile, SIGNAL(triggered()), this, SLOT(actionReloadCompile())); - connect(this->designActionCompile, SIGNAL(triggered()), this, SLOT(actionCompile())); + connect(this->designActionReloadAndCompile, SIGNAL(triggered()), this, SLOT(actionReloadRenderCSG())); + connect(this->designActionCompile, SIGNAL(triggered()), this, SLOT(actionRenderCSG())); #ifdef ENABLE_CGAL connect(this->designActionCompileAndRender, SIGNAL(triggered()), this, SLOT(actionRenderCGAL())); #else @@ -580,7 +586,7 @@ void MainWindow::updateTVal() double fps = this->e_fps->text().toDouble(&fps_ok); if (fps_ok) { if (fps <= 0) { - actionCompile(); + actionRenderCSG(); } else { double s = this->e_fsteps->text().toDouble(); double t = this->e_tval->text().toDouble() + 1/s; @@ -612,14 +618,88 @@ void MainWindow::refreshDocument() } /*! - Parse and evaluate the design => this->root_node - - Returns true if something was compiled, false if nothing was changed - and the root_node was left untouched. + compiles the design. Calls compileDone() if anything was compiled */ -bool MainWindow::compile(bool reload, bool procevents) +void MainWindow::compile(bool reload, bool forcedone) +{ + bool shouldcompiletoplevel = false; + bool didcompile = false; + + // Reload checks the timestamp of the toplevel file and refreshes if necessary, + if (reload) { + if (fileChangedOnDisk() && checkEditorModified()) { + shouldcompiletoplevel = true; + refreshDocument(); + } + } + else { + shouldcompiletoplevel = true; + } + + if (!shouldcompiletoplevel && includesChanged()) { + shouldcompiletoplevel = true; + } + + if (shouldcompiletoplevel) { + compileTopLevelDocument(); + didcompile = true; + } + + if (this->root_module) { + if (this->root_module->handleDependencies()) { + PRINTB("Module cache size: %d modules", ModuleCache::instance()->size()); + didcompile = true; + } + } + + // If we're auto-reloading, listen for a cascade of changes by starting a timer + // if something changed _and_ there are any external dependencies + if (reload && didcompile && this->root_module) { + if (this->root_module->includes.size() > 0 || + this->root_module->usedlibs.size() > 0) { + this->waitAfterReloadTimer->start(); + return; + } + } + compileDone(didcompile | forcedone); +} + +void MainWindow::waitAfterReload() +{ + if (this->root_module->handleDependencies()) { + this->waitAfterReloadTimer->start(); + return; + } + else { + compile(true, true); // In case file itself or top-level includes changed during dependency updates + } +} + +void MainWindow::compileDone(bool didchange) +{ + const char *callslot; + if (didchange) { + instantiateRoot(); + callslot = afterCompileSlot; + } + else { + callslot = "compileEnded"; + } + + this->procevents = false; + QMetaObject::invokeMethod(this, callslot); +} + +void MainWindow::compileEnded() +{ + clearCurrentOutput(); + GuiLocker::unlock(); + if (designActionAutoReload->isChecked()) autoReloadTimer->start(); +} + +void MainWindow::instantiateRoot() { - if (!compileTopLevelDocument(reload)) return false; + // Go on and instantiate root_node, then call the continuation slot // Invalidate renderers before we kill the CSG tree this->qglview->setRenderer(NULL); @@ -652,7 +732,7 @@ bool MainWindow::compile(bool reload, bool procevents) if (this->root_module) { // Evaluate CSG tree PRINT("Compiling design (CSG Tree generation)..."); - if (procevents) QApplication::processEvents(); + if (this->procevents) QApplication::processEvents(); AbstractNode::resetIndexCounter(); this->root_inst = ModuleInstantiation("group"); @@ -677,10 +757,8 @@ bool MainWindow::compile(bool reload, bool procevents) } else { PRINT("ERROR: Compilation failed!"); } - if (procevents) QApplication::processEvents(); + if (this->procevents) QApplication::processEvents(); } - - return true; } /*! @@ -1049,66 +1127,44 @@ bool MainWindow::includesChanged() } /*! - If reload is true, does a timestamp check on the document and tries to reload it. - Otherwise, just reparses the current document and any dependencies, updates the - GUI accordingly and populates this->root_module. - Returns true if anything was compiled. */ -bool MainWindow::compileTopLevelDocument(bool reload) +void MainWindow::compileTopLevelDocument() { - bool shouldcompiletoplevel = !reload; - - if (includesChanged()) shouldcompiletoplevel = true; - - if (reload && fileChangedOnDisk() && checkEditorModified()) { - shouldcompiletoplevel = true; - refreshDocument(); - } + console->clear(); - if (shouldcompiletoplevel) { - console->clear(); - - updateTemporalVariables(); - - this->last_compiled_doc = editor->toPlainText(); - std::string fulltext = - std::string(this->last_compiled_doc.toLocal8Bit().constData()) + - "\n" + commandline_commands; - - delete this->root_module; - this->root_module = NULL; - - this->root_module = parse(fulltext.c_str(), - this->fileName.isEmpty() ? - "" : - QFileInfo(this->fileName).absolutePath().toLocal8Bit(), - false); - - if (!animate_panel->isVisible()) { - highlighter->unhighlightLastError(); - if (!this->root_module) { - QTextCursor cursor = editor->textCursor(); - cursor.setPosition(parser_error_pos); - editor->setTextCursor(cursor); - highlighter->highlightError( parser_error_pos ); - } + updateTemporalVariables(); + + this->last_compiled_doc = editor->toPlainText(); + std::string fulltext = + std::string(this->last_compiled_doc.toLocal8Bit().constData()) + + "\n" + commandline_commands; + + delete this->root_module; + this->root_module = NULL; + + this->root_module = parse(fulltext.c_str(), + this->fileName.isEmpty() ? + "" : + QFileInfo(this->fileName).absolutePath().toLocal8Bit(), + false); + + if (!animate_panel->isVisible()) { + highlighter->unhighlightLastError(); + if (!this->root_module) { + QTextCursor cursor = editor->textCursor(); + cursor.setPosition(parser_error_pos); + editor->setTextCursor(cursor); + highlighter->highlightError( parser_error_pos ); } - - } - - bool changed = shouldcompiletoplevel; - if (this->root_module) { - changed |= this->root_module->handleDependencies(); - if (changed) PRINTB("Module cache size: %d modules", ModuleCache::instance()->size()); } - - return changed; } void MainWindow::checkAutoReload() { - if (!this->fileName.isEmpty()) actionReloadCompile(); + if (!this->fileName.isEmpty()) { + actionReloadRenderCSG(); + } } void MainWindow::autoReloadSet(bool on) @@ -1117,7 +1173,7 @@ void MainWindow::autoReloadSet(bool on) settings.setValue("design/autoReload",designActionAutoReload->isChecked()); if (on) { autoReloadId = ""; - autoReloadTimer->start(200); + autoReloadTimer->start(); } else { autoReloadTimer->stop(); } @@ -1139,15 +1195,22 @@ bool MainWindow::checkEditorModified() return true; } -void MainWindow::actionReloadCompile() +void MainWindow::actionReloadRenderCSG() { if (GuiLocker::isLocked()) return; - GuiLocker lock; + GuiLocker::lock(); + autoReloadTimer->stop(); setCurrentOutput(); // PRINT("Parsing design (AST generation)..."); // QApplication::processEvents(); - if (!compile(true, true)) return; + this->afterCompileSlot = "csgReloadRender"; + this->procevents = true; + compile(true); +} + +void MainWindow::csgReloadRender() +{ if (this->root_node) compileCSG(true); // Go to non-CGAL view mode @@ -1161,20 +1224,26 @@ void MainWindow::actionReloadCompile() viewModeThrownTogether(); #endif } - - clearCurrentOutput(); + compileEnded(); } -void MainWindow::actionCompile() +void MainWindow::actionRenderCSG() { if (GuiLocker::isLocked()) return; - GuiLocker lock; + GuiLocker::lock(); + autoReloadTimer->stop(); setCurrentOutput(); console->clear(); PRINT("Parsing design (AST generation)..."); QApplication::processEvents(); - compile(false, !viewActionAnimate->isChecked()); + this->afterCompileSlot = "csgRender"; + this->procevents = !viewActionAnimate->isChecked(); + compile(false); +} + +void MainWindow::csgRender() +{ if (this->root_node) compileCSG(!viewActionAnimate->isChecked()); // Go to non-CGAL view mode @@ -1198,7 +1267,7 @@ void MainWindow::actionCompile() img.save(filename, "PNG"); } - clearCurrentOutput(); + compileEnded(); } #ifdef ENABLE_CGAL @@ -1206,15 +1275,20 @@ void MainWindow::actionCompile() void MainWindow::actionRenderCGAL() { if (GuiLocker::isLocked()) return; - GuiLocker lock; - + GuiLocker::lock(); + autoReloadTimer->stop(); setCurrentOutput(); console->clear(); PRINT("Parsing design (AST generation)..."); QApplication::processEvents(); - compile(false, true); + this->afterCompileSlot = "cgalRender"; + this->procevents = true; + compile(false); +} +void MainWindow::cgalRender() +{ if (!this->root_module || !this->root_node) { return; } @@ -1234,7 +1308,6 @@ void MainWindow::actionRenderCGAL() progress_report_prep(this->root_node, report_func, this); - GuiLocker::lock(); // Will be unlocked in actionRenderCGALDone() this->cgalworker->start(this->tree); } @@ -1297,9 +1370,7 @@ void MainWindow::actionRenderCGALDone(CGAL_Nef_polyhedron *root_N) this->statusBar()->removeWidget(this->progresswidget); delete this->progresswidget; this->progresswidget = NULL; - clearCurrentOutput(); - - GuiLocker::unlock(); + compileEnded(); } #endif /* ENABLE_CGAL */ @@ -1612,7 +1683,7 @@ void MainWindow::viewModeAnimate() { if (viewActionAnimate->isChecked()) { animate_panel->show(); - actionCompile(); + actionRenderCSG(); updatedFps(); } else { animate_panel->hide(); |