diff --git a/src/MainWindow.h b/src/MainWindow.h index f08e3513..a1d874f4 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -181,7 +181,7 @@ public slots: void viewCenter(); void viewPerspective(); void viewOrthogonal(); - void viewResetView(); + void viewResetView(); void hideConsole(); void animateUpdateDocChanged(); void animateUpdate(); @@ -198,14 +198,14 @@ public slots: private: static void report_func(const class AbstractNode*, void *vp, int mark); - + char const * afterCompileSlot; bool procevents; class QTemporaryFile *tempFile; - class ProgressWidget *progresswidget; class CGALWorker *cgalworker; QMutex consolemutex; + signals: void highlightError(int); void unhighlightLastError(); diff --git a/src/MainWindow.ui b/src/MainWindow.ui index f5d4b768..614fa2a8 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -126,6 +126,9 @@ 8 + + Qt::WheelFocus + @@ -139,6 +142,9 @@ + + Qt::ClickFocus + true @@ -328,6 +334,9 @@ + + + @@ -864,6 +873,22 @@ Reset View + + + Zoom In + + + Ctrl+] + + + + + Zoom Out + + + Ctrl+[ + + diff --git a/src/QGLView.cc b/src/QGLView.cc index 83acf23d..27659f90 100644 --- a/src/QGLView.cc +++ b/src/QGLView.cc @@ -170,25 +170,6 @@ void QGLView::paintGL() if (running_under_wine) swapBuffers(); } -void QGLView::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Plus: // On many keyboards, this requires to press Shift-equals - case Qt::Key_Equal: // ...so simplify this a bit. - cam.viewer_distance *= 0.9; - updateGL(); - break; - case Qt::Key_Minus: - cam.viewer_distance /= 0.9; - updateGL(); - break; - case Qt::Key_C: // 'center' - cam.object_trans << 0, 0, 0; - updateGL(); - break; - } -} - void QGLView::wheelEvent(QWheelEvent *event) { cam.viewer_distance *= pow(0.9, event->delta() / 120.0); @@ -197,7 +178,6 @@ void QGLView::wheelEvent(QWheelEvent *event) void QGLView::mousePressEvent(QMouseEvent *event) { - setFocus(); mouse_drag_active = true; last_mouse = event->globalPos(); } @@ -298,3 +278,14 @@ bool QGLView::save(const char *filename) return img.save(filename, "PNG"); } +void QGLView::ZoomIn(void) +{ + cam.viewer_distance *= 0.9; + updateGL(); +} + +void QGLView::ZoomOut(void) +{ + cam.viewer_distance /= 0.9; + updateGL(); +} diff --git a/src/QGLView.h b/src/QGLView.h index aaab8f57..a2a4d49b 100644 --- a/src/QGLView.h +++ b/src/QGLView.h @@ -44,7 +44,11 @@ public: float getDPI() { return this->devicePixelRatio(); } #endif bool save(const char *filename); - void resetView(); + void resetView(); + +public slots: + void ZoomIn(void); + void ZoomOut(void); public: QLabel *statusLabel; @@ -55,7 +59,6 @@ private: bool mouse_drag_active; QPoint last_mouse; - void keyPressEvent(QKeyEvent *event); void wheelEvent(QWheelEvent *event); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); diff --git a/src/mainwin.cc b/src/mainwin.cc index 6098e236..d4c71eab 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -171,7 +171,7 @@ MainWindow::MainWindow(const QString &filename) #ifdef ENABLE_CGAL this->cgalworker = new CGALWorker(); - connect(this->cgalworker, SIGNAL(done(CGAL_Nef_polyhedron *)), + connect(this->cgalworker, SIGNAL(done(CGAL_Nef_polyhedron *)), this, SLOT(actionRenderCGALDone(CGAL_Nef_polyhedron *))); #endif @@ -198,6 +198,8 @@ MainWindow::MainWindow(const QString &filename) fps = 0; fsteps = 1; + editActionZoomIn->setShortcuts(QList() << editActionZoomIn->shortcuts() << QKeySequence("CTRL+=")); + connect(this, SIGNAL(highlightError(int)), editor, SLOT(highlightError(int))); connect(this, SIGNAL(unhighlightLastError()), editor, SLOT(unhighlightLastError())); editor->setTabStopWidth(30); @@ -265,7 +267,7 @@ MainWindow::MainWindow(const QString &filename) this, SLOT(clearRecentFiles())); if (!qexamplesdir.isEmpty()) { bool found_example = false; - QStringList examples = QDir(qexamplesdir).entryList(QStringList("*.scad"), + QStringList examples = QDir(qexamplesdir).entryList(QStringList("*.scad"), QDir::Files | QDir::Readable, QDir::Name); foreach (const QString &ex, examples) { this->menuExamples->addAction(ex, this, SLOT(actionOpenExample())); @@ -357,6 +359,8 @@ MainWindow::MainWindow(const QString &filename) connect(this->viewActionPerspective, SIGNAL(triggered()), this, SLOT(viewPerspective())); connect(this->viewActionOrthogonal, SIGNAL(triggered()), this, SLOT(viewOrthogonal())); connect(this->viewActionHide, SIGNAL(triggered()), this, SLOT(hideConsole())); + connect(this->viewActionZoomIn, SIGNAL(triggered()), qglview, SLOT(ZoomIn())); + connect(this->viewActionZoomOut, SIGNAL(triggered()), qglview, SLOT(ZoomOut())); // Help menu connect(this->helpActionAbout, SIGNAL(triggered()), this, SLOT(helpAbout())); @@ -384,11 +388,11 @@ MainWindow::MainWindow(const QString &filename) connect(this->qglview, SIGNAL(doAnimateUpdate()), this, SLOT(animateUpdate())); connect(Preferences::inst(), SIGNAL(requestRedraw()), this->qglview, SLOT(updateGL())); - connect(Preferences::inst(), SIGNAL(fontChanged(const QString&,uint)), + connect(Preferences::inst(), SIGNAL(fontChanged(const QString&,uint)), this, SLOT(setFont(const QString&,uint))); connect(Preferences::inst(), SIGNAL(openCSGSettingsChanged()), this, SLOT(openCSGSettingsChanged())); - connect(Preferences::inst(), SIGNAL(syntaxHighlightChanged(const QString&)), + connect(Preferences::inst(), SIGNAL(syntaxHighlightChanged(const QString&)), editor, SLOT(setHighlightScheme(const QString&))); Preferences::inst()->apply(); @@ -496,7 +500,7 @@ void MainWindow::report_func(const class AbstractNode*, void *vp, int mark) { MainWindow *thisp = static_cast(vp); int v = (int)((mark*1000.0) / progress_report_count); - int permille = v < 1000 ? v : 999; + int permille = v < 1000 ? v : 999; if (permille > thisp->progresswidget->value()) { QMetaObject::invokeMethod(thisp->progresswidget, "setValue", Qt::QueuedConnection, Q_ARG(int, permille)); @@ -568,7 +572,7 @@ MainWindow::setFileName(const QString &filename) } else { this->fileName = fileinfo.fileName(); } - + this->top_ctx.setDocumentPath(fileinfo.dir().absolutePath().toLocal8Bit().constData()); QDir::setCurrent(fileinfo.dir().absolutePath()); } @@ -632,7 +636,7 @@ void MainWindow::refreshDocument() if (!this->fileName.isEmpty()) { QFile file(this->fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - PRINTB("Failed to open file %s: %s", + PRINTB("Failed to open file %s: %s", this->fileName.toLocal8Bit().constData() % file.errorString().toLocal8Bit().constData()); } else { @@ -783,15 +787,15 @@ void MainWindow::instantiateRoot() // Evaluate CSG tree PRINT("Compiling design (CSG Tree generation)..."); if (this->procevents) QApplication::processEvents(); - + AbstractNode::resetIndexCounter(); // split these two lines - gcc 4.7 bug ModuleInstantiation mi = ModuleInstantiation( "group" ); - this->root_inst = mi; + this->root_inst = mi; this->absolute_root_node = this->root_module->instantiate(&top_ctx, &this->root_inst, NULL); - + if (this->absolute_root_node) { // Do we have an explicit root node (! modifier)? if (!(this->root_node = find_root_tag(this->absolute_root_node))) { @@ -863,7 +867,7 @@ void MainWindow::compileCSG(bool procevents) if (root_raw_term) { PRINT("Compiling design (CSG Products normalization)..."); if (procevents) QApplication::processEvents(); - + size_t normalizelimit = 2 * Preferences::inst()->getValue("advanced/openCSGLimit").toUInt(); CSGTermNormalizer normalizer(normalizelimit); this->root_norm_term = normalizer.normalize(this->root_raw_term); @@ -876,24 +880,24 @@ void MainWindow::compileCSG(bool procevents) PRINT("WARNING: CSG normalization resulted in an empty tree"); if (procevents) QApplication::processEvents(); } - + if (highlight_terms.size() > 0) { PRINTB("Compiling highlights (%d CSG Trees)...", highlight_terms.size()); if (procevents) QApplication::processEvents(); - + highlights_chain = new CSGChain(); for (unsigned int i = 0; i < highlight_terms.size(); i++) { highlight_terms[i] = normalizer.normalize(highlight_terms[i]); highlights_chain->import(highlight_terms[i]); } } - + if (background_terms.size() > 0) { PRINTB("Compiling background (%d CSG Trees)...", background_terms.size()); if (procevents) QApplication::processEvents(); - + background_chain = new CSGChain(); for (unsigned int i = 0; i < background_terms.size(); i++) { background_terms[i] = normalizer.normalize(background_terms[i]); @@ -901,22 +905,22 @@ void MainWindow::compileCSG(bool procevents) } } - if (this->root_chain && - (this->root_chain->objects.size() > + if (this->root_chain && + (this->root_chain->objects.size() > Preferences::inst()->getValue("advanced/openCSGLimit").toUInt())) { PRINTB("WARNING: Normalized tree has %d elements!", this->root_chain->objects.size()); PRINT("WARNING: OpenCSG rendering has been disabled."); } else { - PRINTB("Normalized CSG tree has %d elements", + PRINTB("Normalized CSG tree has %d elements", (this->root_chain ? this->root_chain->objects.size() : 0)); - this->opencsgRenderer = new OpenCSGRenderer(this->root_chain, - this->highlights_chain, - this->background_chain, + this->opencsgRenderer = new OpenCSGRenderer(this->root_chain, + this->highlights_chain, + this->background_chain, this->qglview->shaderinfo); } - this->thrownTogetherRenderer = new ThrownTogetherRenderer(this->root_chain, - this->highlights_chain, + this->thrownTogetherRenderer = new ThrownTogetherRenderer(this->root_chain, + this->highlights_chain, this->background_chain); PRINT("CSG generation finished."); int s = t.elapsed() / 1000; @@ -957,7 +961,7 @@ void MainWindow::actionOpen() if (!new_filename.isEmpty()) { if (!maybeSave()) return; - + setCurrentOutput(); openFile(new_filename); clearCurrentOutput(); @@ -1040,7 +1044,7 @@ void MainWindow::writeBackup(QFile *file) QTextStream writer(file); writer.setCodec("UTF-8"); writer << this->editor->toPlainText(); - + PRINTB("Saved backup file: %s", file->fileName().toLocal8Bit().constData()); } @@ -1272,13 +1276,13 @@ bool MainWindow::eventFilter(QObject* obj, QEvent *event) void MainWindow::updateTemporalVariables() { this->top_ctx.set_variable("$t", Value(this->e_tval->text().toDouble())); - + Value::VectorType vpt; vpt.push_back(Value(-qglview->cam.object_trans.x())); vpt.push_back(Value(-qglview->cam.object_trans.y())); vpt.push_back(Value(-qglview->cam.object_trans.z())); this->top_ctx.set_variable("$vpt", Value(vpt)); - + Value::VectorType vpr; vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.x() + 90, 360))); vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.y(), 360))); @@ -1316,21 +1320,21 @@ void MainWindow::compileTopLevelDocument() { updateTemporalVariables(); resetPrintedDeprecations(); - + this->last_compiled_doc = editor->toPlainText(); - std::string fulltext = + 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(), + this->fileName.isEmpty() ? + "" : + QFileInfo(this->fileName).absolutePath().toLocal8Bit(), false); - + } void MainWindow::checkAutoReload() @@ -1437,7 +1441,7 @@ void MainWindow::csgRender() filename.sprintf("frame%05d.png", int(round(s*t))); img.save(filename, "PNG"); } - + compileEnded(); } @@ -1503,7 +1507,7 @@ void MainWindow::actionRenderCGALDone(CGAL_Nef_polyhedron *root_N) PRINTB(" FaceCycles: %6d", root_N->p2->explorer().number_of_face_cycles()); PRINTB(" ConnComp: %6d", root_N->p2->explorer().number_of_connected_components()); } - + if (root_N->dim == 3) { PRINT(" Top level object is a 3D object:"); PRINTB(" Simple: %6s", (root_N->p3->is_simple() ? "yes" : "no")); @@ -1529,7 +1533,7 @@ void MainWindow::actionRenderCGALDone(CGAL_Nef_polyhedron *root_N) else { viewModeCGALSurface(); } - + PRINT("Rendering finished."); } else { @@ -1590,10 +1594,10 @@ void MainWindow::actionDisplayCSGProducts() e->setWindowTitle("CSG Products Dump"); e->setReadOnly(true); e->setPlainText(QString("\nCSG before normalization:\n%1\n\n\nCSG after normalization:\n%2\n\n\nCSG rendering chain:\n%3\n\n\nHighlights CSG rendering chain:\n%4\n\n\nBackground CSG rendering chain:\n%5\n") - .arg(root_raw_term ? QString::fromLocal8Bit(root_raw_term->dump().c_str()) : "N/A", - root_norm_term ? QString::fromLocal8Bit(root_norm_term->dump().c_str()) : "N/A", - this->root_chain ? QString::fromLocal8Bit(this->root_chain->dump().c_str()) : "N/A", - highlights_chain ? QString::fromLocal8Bit(highlights_chain->dump().c_str()) : "N/A", + .arg(root_raw_term ? QString::fromLocal8Bit(root_raw_term->dump().c_str()) : "N/A", + root_norm_term ? QString::fromLocal8Bit(root_norm_term->dump().c_str()) : "N/A", + this->root_chain ? QString::fromLocal8Bit(this->root_chain->dump().c_str()) : "N/A", + highlights_chain ? QString::fromLocal8Bit(highlights_chain->dump().c_str()) : "N/A", background_chain ? QString::fromLocal8Bit(background_chain->dump().c_str()) : "N/A")); e->show(); e->resize(600, 400); @@ -1655,7 +1659,7 @@ void MainWindow::actionExportSTLorOFF(bool) QString suffix = stl_mode ? ".stl" : ".off"; QString stl_filename = QFileDialog::getSaveFileName(this, - stl_mode ? "Export STL File" : "Export OFF File", + stl_mode ? "Export STL File" : "Export OFF File", this->fileName.isEmpty() ? "Untitled"+suffix : QFileInfo(this->fileName).baseName()+suffix, stl_mode ? "STL Files (*.stl)" : "OFF Files (*.off)"); if (stl_filename.isEmpty()) { @@ -1708,7 +1712,7 @@ void MainWindow::actionExportDXF() } QString dxf_filename = QFileDialog::getSaveFileName(this, - "Export DXF File", + "Export DXF File", this->fileName.isEmpty() ? "Untitled.dxf" : QFileInfo(this->fileName).baseName()+".dxf", "DXF Files (*.dxf)"); if (dxf_filename.isEmpty()) { @@ -1741,7 +1745,7 @@ void MainWindow::actionExportCSG() return; } - QString csg_filename = QFileDialog::getSaveFileName(this, "Export CSG File", + QString csg_filename = QFileDialog::getSaveFileName(this, "Export CSG File", this->fileName.isEmpty() ? "Untitled.csg" : QFileInfo(this->fileName).baseName()+".csg", "CSG Files (*.csg)"); if (csg_filename.isEmpty()) {