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).
master
Sławomir Demeszko 2014-04-11 01:18:08 +02:00
parent fcf7b27257
commit ff555d760b
5 changed files with 93 additions and 70 deletions

View File

@ -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();

View File

@ -126,6 +126,9 @@
<pointsize>8</pointsize>
</font>
</property>
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
</widget>
</item>
</layout>
@ -139,6 +142,9 @@
</property>
<widget class="QGLView" name="qglview" native="true"/>
<widget class="QTextEdit" name="console">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
@ -328,6 +334,9 @@
<addaction name="viewActionDiagonal"/>
<addaction name="viewActionCenter"/>
<addaction name="separator"/>
<addaction name="viewActionZoomIn"/>
<addaction name="viewActionZoomOut"/>
<addaction name="separator"/>
<addaction name="viewActionResetView"/>
<addaction name="separator"/>
<addaction name="viewActionPerspective"/>
@ -864,6 +873,22 @@
<string>Reset View</string>
</property>
</action>
<action name="viewActionZoomIn">
<property name="text">
<string>Zoom In</string>
</property>
<property name="shortcut">
<string>Ctrl+]</string>
</property>
</action>
<action name="viewActionZoomOut">
<property name="text">
<string>Zoom Out</string>
</property>
<property name="shortcut">
<string>Ctrl+[</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -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();
}

View File

@ -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);

View File

@ -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<QKeySequence>() << 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<MainWindow*>(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()) {