From ff555d760b7d8cbf0d77f7aa798d2753541649d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C5=82awomir=20Demeszko?= Date: Fri, 11 Apr 2014 01:18:08 +0200 Subject: [PATCH] Preventing loosing keyboard focus by editor. When you write your code in editor sometimes you want to rotate or move object on 3D view, but due stealing focus by this widget it is quite tedious. You need additional mouse click to return focus to editor and search line where you last edited. This behavior is not neccessary as we can interpret keyboard events globally (in MainWindow) and send commands to 3D view. Console window need ClickFocus to show context menu. Zoom In/Out 3D view is assigned to CTRL+[ and CTRL+]. Adding also additional shortcut to zoom in editor font CTRL+= (with CTRL++ SHIFT is necessary). --- src/MainWindow.h | 6 +-- src/MainWindow.ui | 25 +++++++++++++ src/QGLView.cc | 31 ++++++---------- src/QGLView.h | 7 +++- src/mainwin.cc | 94 ++++++++++++++++++++++++----------------------- 5 files changed, 93 insertions(+), 70 deletions(-) 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()) {