diff --git a/src/Gui/DlgSettingsNavigation.cpp b/src/Gui/DlgSettingsNavigation.cpp index 549889c6d9..79a96e1d8f 100644 --- a/src/Gui/DlgSettingsNavigation.cpp +++ b/src/Gui/DlgSettingsNavigation.cpp @@ -36,6 +36,7 @@ #include "DlgSettingsNavigation.h" #include "ui_DlgSettingsNavigation.h" #include "MainWindow.h" +#include "NaviCube.h" #include "NavigationStyle.h" #include "View3DInventor.h" #include "View3DInventorViewer.h" @@ -72,7 +73,8 @@ void DlgSettingsNavigation::saveSettings() // where we set some attributes afterwards ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath ("User parameter:BaseApp/Preferences/View"); - QVariant data = ui->comboNavigationStyle->itemData(ui->comboNavigationStyle->currentIndex(), Qt::UserRole); + QVariant data = ui->comboNavigationStyle->itemData(ui->comboNavigationStyle->currentIndex(), + Qt::UserRole); hGrp->SetASCII("NavigationStyle", (const char*)data.toByteArray()); int index = ui->comboOrbitStyle->currentIndex(); @@ -90,11 +92,13 @@ void DlgSettingsNavigation::saveSettings() ui->naviCubeCorner->onSave(); ui->naviCubeToNearest->onSave(); ui->prefCubeSize->onSave(); + ui->naviCubeFontSize->onSave(); bool showNaviCube = ui->groupBoxNaviCube->isChecked(); hGrp->SetBool("ShowNaviCube", showNaviCube); - QVariant camera = ui->comboNewDocView->itemData(ui->comboNewDocView->currentIndex(), Qt::UserRole); + QVariant camera = ui->comboNewDocView->itemData(ui->comboNewDocView->currentIndex(), + Qt::UserRole); hGrp->SetASCII("NewDocumentCameraOrientation", (const char*)camera.toByteArray()); if (camera == QByteArray("Custom")) { ParameterGrp::handle hCustom = hGrp->GetGroup("Custom"); @@ -103,6 +107,19 @@ void DlgSettingsNavigation::saveSettings() hCustom->SetFloat("Q2", q2); hCustom->SetFloat("Q3", q3); } + + hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/NaviCube"); + hGrp->SetASCII("FontString", ui->naviCubeFontName->currentText().toLatin1()); + + // we changed the cube's layout, therefore we must re-initialize it + // by deleting and the subsequently recreating + auto mdi = qobject_cast(getMainWindow()->activeWindow()); + if (mdi) { + auto currentView = mdi->getViewer(); + currentView->deleteNavigationCube(); + currentView->createNavigationCube(); + } } void DlgSettingsNavigation::loadSettings() @@ -117,6 +134,7 @@ void DlgSettingsNavigation::loadSettings() ui->naviCubeCorner->onRestore(); ui->naviCubeToNearest->onRestore(); ui->prefCubeSize->onRestore(); + ui->naviCubeFontSize->onRestore(); ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath ("User parameter:BaseApp/Preferences/View"); @@ -157,6 +175,24 @@ void DlgSettingsNavigation::loadSettings() connect(ui->comboNewDocView, SIGNAL(currentIndexChanged(int)), this, SLOT(onNewDocViewChanged(int))); + + // fill up font styles + hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/NaviCube"); + QByteArray defaultSansserifFont = NaviCube::getDefaultSansserifFont().family().toLatin1(); + + // we purposely allow all available fonts on the system +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QStringList familyNames = QFontDatabase().families(QFontDatabase::Any); +#else + QStringList familyNames = QFontDatabase::families(QFontDatabase::Any); +#endif + ui->naviCubeFontName->addItems(familyNames); + int indexFamilyNames = familyNames.indexOf( + QString::fromLatin1(hGrp->GetASCII("FontString", defaultSansserifFont).c_str())); + if (indexFamilyNames < 0) + indexFamilyNames = 0; + ui->naviCubeFontName->setCurrentIndex(indexFamilyNames); } void DlgSettingsNavigation::on_mouseButton_clicked() @@ -165,10 +201,12 @@ void DlgSettingsNavigation::on_mouseButton_clicked() Ui_MouseButtons uimb; uimb.setupUi(&dlg); - QVariant data = ui->comboNavigationStyle->itemData(ui->comboNavigationStyle->currentIndex(), Qt::UserRole); + QVariant data = + ui->comboNavigationStyle->itemData(ui->comboNavigationStyle->currentIndex(), Qt::UserRole); void* instance = Base::Type::createInstanceByName((const char*)data.toByteArray()); std::unique_ptr ns(static_cast(instance)); - uimb.groupBox->setTitle(uimb.groupBox->title()+QString::fromLatin1(" ")+ui->comboNavigationStyle->currentText()); + uimb.groupBox->setTitle(uimb.groupBox->title() + QString::fromLatin1(" ") + + ui->comboNavigationStyle->currentText()); QString descr; descr = qApp->translate((const char*)data.toByteArray(),ns->mouseButtons(NavigationStyle::SELECTION)); descr.replace(QLatin1String("\n"), QLatin1String("

")); diff --git a/src/Gui/DlgSettingsNavigation.ui b/src/Gui/DlgSettingsNavigation.ui index 391576afde..f9bc6c340e 100644 --- a/src/Gui/DlgSettingsNavigation.ui +++ b/src/Gui/DlgSettingsNavigation.ui @@ -7,13 +7,13 @@ 0 0 500 - 391 + 394 Navigation - + @@ -117,7 +117,7 @@ - + Rotates to nearest possible state when clicking a cube face @@ -136,14 +136,37 @@ - + + + + Font name: + + + + + + + Corner where navigation cube is shown + + + -1 + + + FontString + + + NaviCube + + + + Cube size - + Size of the navigation cube @@ -171,6 +194,44 @@ + + + + Font size: + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Font size for the NaviCube text</p></body></html> + + + 1 + + + 999 + + + 5 + + + 100 + + + FontSize + + + NaviCube + + + diff --git a/src/Gui/NaviCube.cpp b/src/Gui/NaviCube.cpp index f1b0ba6202..2e91ad4b15 100644 --- a/src/Gui/NaviCube.cpp +++ b/src/Gui/NaviCube.cpp @@ -51,7 +51,6 @@ #include "Application.h" #include "Command.h" #include "MainWindow.h" - #include "View3DInventorViewer.h" #include "View3DInventor.h" @@ -120,6 +119,7 @@ public: void OnChange(ParameterGrp::SubjectType& rCaller, ParameterGrp::MessageType Reason) override; bool processSoEvent(const SoEvent* ev); + private: bool mousePressed(short x, short y); bool mouseReleased(short x, short y); @@ -146,6 +146,7 @@ private: QString str(const char* str); char* enum2str(int); QMenu* createNaviCubeMenu(); + public: enum { // TEX_FRONT = 1, // 0 is reserved for 'nothing picked' @@ -213,6 +214,8 @@ public: bool m_MightDrag = false; double m_BorderWidth; NaviCube::Corner m_Corner = NaviCube::TopRightCorner; + int m_CubeTextSize = 0; + std::string m_CubeTextString; QtGLFramebufferObject* m_PickingFramebuffer; @@ -251,7 +254,6 @@ bool NaviCube::processSoEvent(const SoEvent* ev) { return m_NaviCubeImplementation->processSoEvent(ev); } - vector NaviCubeImplementation::m_commands; vector NaviCubeImplementation::m_labels; @@ -261,21 +263,44 @@ void NaviCube::setCorner(Corner c) { m_NaviCubeImplementation->m_PrevHeight = 0; } +// sets a default sansserif font +// the Helvetica font is a good start for most OSes +QFont NaviCube::getDefaultSansserifFont() +{ + QFont font(QString::fromLatin1("Helvetica")); + if (font.styleHint() & QFont::SansSerif) + return font; + // on Windows 11 there is no longer a Helvetia font + // therefore if we did not found a Helvetica font check for + // the DejaVu Sans which is in Windows 11 + font.setFamily(QString::fromLatin1("DejaVu Sans")); + // on Windows 11 sansserif fonts like DejaVu Sans does not have the + // styleHint QFont::SansSerif but QFont::AnyStyle + // however, in future they might have, thus allow both + if (font.styleHint() == QFont::SansSerif || font.styleHint() == QFont::AnyStyle) + return font; + return font; // We failed, but return whatever we have anyway +} + NaviCubeImplementation::NaviCubeImplementation( Gui::View3DInventorViewer* viewer) { m_View3DInventorViewer = viewer; - auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/NaviCube"); + auto hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/NaviCube"); hGrp->Attach(this); OnChange(*hGrp, "TextColor"); OnChange(*hGrp, "FrontColor"); OnChange(*hGrp, "HiliteColor"); OnChange(*hGrp, "ButtonColor"); + OnChange(*hGrp, "CornerNaviCube"); OnChange(*hGrp, "CubeSize"); OnChange(*hGrp, "BorderWidth"); OnChange(*hGrp, "BorderColor"); + OnChange(*hGrp, "FontSize"); + OnChange(*hGrp, "FontString"); m_PickingFramebuffer = nullptr; m_Menu = createNaviCubeMenu(); @@ -294,10 +319,11 @@ NaviCubeImplementation::~NaviCubeImplementation() { delete* t; } -void NaviCubeImplementation::OnChange(ParameterGrp::SubjectType& rCaller, ParameterGrp::MessageType reason) +void NaviCubeImplementation::OnChange(ParameterGrp::SubjectType& rCaller, + ParameterGrp::MessageType reason) { const auto& rGrp = static_cast(rCaller); - + if (strcmp(reason, "TextColor") == 0) { m_TextColor.setRgba(rGrp.GetUnsigned(reason, QColor(0, 0, 0, 255).rgba())); } @@ -310,15 +336,25 @@ void NaviCubeImplementation::OnChange(ParameterGrp::SubjectType& rCaller, Parame else if (strcmp(reason, "ButtonColor") == 0) { m_ButtonColor.setRgba(rGrp.GetUnsigned(reason, QColor(226, 233, 239, 128).rgba())); } + else if (strcmp(reason, "CornerNaviCube") == 0) { + m_Corner = static_cast(rGrp.GetInt(reason, 1)); + } else if (strcmp(reason, "CubeSize") == 0) { - m_CubeWidgetSize = (rGrp.GetInt(reason, 132)); + m_CubeWidgetSize = rGrp.GetInt(reason, 132); } else if (strcmp(reason, "BorderWidth") == 0) { - m_BorderWidth = rGrp.GetFloat("BorderWidth", 1.1); + m_BorderWidth = rGrp.GetFloat(reason, 1.1); } else if (strcmp(reason, "BorderColor") == 0) { m_BorderColor.setRgba(rGrp.GetUnsigned(reason, QColor(50, 50, 50, 255).rgba())); } + else if (strcmp(reason, "FontSize") == 0) { + m_CubeTextSize = rGrp.GetInt(reason, 100); + } + else if (strcmp(reason, "FontString") == 0) { + m_CubeTextString = (rGrp.GetASCII( + reason, NaviCube::getDefaultSansserifFont().family().toStdString().c_str())); + } } char* NaviCubeImplementation::enum2str(int positionEnum) { @@ -381,7 +417,9 @@ auto convertWeights = [](int weight) -> QFont::Weight { return QFont::Thin; }; -GLuint NaviCubeImplementation::createCubeFaceTex(QtGLWidget* gl, float gap, const char* text, int shape) { +GLuint NaviCubeImplementation::createCubeFaceTex(QtGLWidget* gl, float gap, const char* text, + int shape) +{ int texSize = m_CubeWidgetSize * m_OverSample; float gapi = texSize * gap; QImage image(texSize, texSize, QImage::Format_ARGB32); @@ -391,17 +429,22 @@ GLuint NaviCubeImplementation::createCubeFaceTex(QtGLWidget* gl, float gap, cons paint.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); if (text) { - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/NaviCube"); + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/NaviCube"); paint.setPen(Qt::white); - QFont sansFont(str("Helvetica"), 0.18 * texSize); + QFont sansFont; + // check the user settings QString fontString = QString::fromUtf8((hGrp->GetASCII("FontString")).c_str()); if (fontString.isEmpty()) { + // load a font as start + sansFont.fromString(NaviCube::getDefaultSansserifFont().family()); + sansFont.setPointSize(int(0.18 * texSize)); // Improving readability sansFont.setWeight(convertWeights(hGrp->GetInt("FontWeight", 87))); sansFont.setStretch(hGrp->GetInt("FontStretch", 62)); - } - else { - sansFont.fromString(fontString); + // store font size and name + hGrp->SetInt("FontSize", sansFont.pointSize()); + hGrp->SetASCII("FontString", sansFont.family().toStdString()); } // Override fromString if (hGrp->GetInt("FontWeight") > 0) { @@ -410,13 +453,18 @@ GLuint NaviCubeImplementation::createCubeFaceTex(QtGLWidget* gl, float gap, cons if (hGrp->GetInt("FontStretch") > 0) { sansFont.setStretch(hGrp->GetInt("FontStretch")); } + sansFont.fromString(QString::fromStdString(m_CubeTextString)); + sansFont.setPointSize(m_CubeTextSize); paint.setFont(sansFont); - paint.drawText(QRect(0, 0, texSize, texSize), Qt::AlignCenter, qApp->translate("Gui::NaviCube", text)); + paint.drawText( + QRect(0, 0, texSize, texSize), Qt::AlignCenter, qApp->translate("Gui::NaviCube", text)); } else if (shape == SHAPE_SQUARE) { QPainterPath pathSquare; - auto rectSquare = QRectF(gapi, gapi, (qreal)texSize - 2.0 * gapi, (qreal)texSize - 2.0 * gapi); - // Qt's coordinate system is x->left y->down, this must be taken into account on operations + auto rectSquare = + QRectF(gapi, gapi, (qreal)texSize - 2.0 * gapi, (qreal)texSize - 2.0 * gapi); + // Qt's coordinate system is x->left y->down, + // this must be taken into account on operations pathSquare.moveTo(rectSquare.left() , rectSquare.bottom() - gapi); pathSquare.lineTo(rectSquare.left() + gapi , rectSquare.bottom()); pathSquare.lineTo(rectSquare.right() - gapi , rectSquare.bottom()); @@ -461,7 +509,6 @@ GLuint NaviCubeImplementation::createCubeFaceTex(QtGLWidget* gl, float gap, cons return texture->textureId(); } - GLuint NaviCubeImplementation::createButtonTex(QtGLWidget* gl, int button) { int texSize = m_CubeWidgetSize * m_OverSample; QImage image(texSize, texSize, QImage::Format_ARGB32); @@ -693,9 +740,9 @@ void NaviCubeImplementation::addFace(float gap, const Vector3f& x, const Vector3 } // TEX_TOP, TEX_FRONT_FACE, TEX_TOP - // TEX_TOP frontTex, - // TEX_FRONT_FACE pickTex, - // TEX_TOP pickId + // TEX_TOP frontTex, + // TEX_FRONT_FACE pickTex, + // TEX_TOP pickId Face* FaceFront = new Face( m_IndexArray.size(), 4, @@ -963,7 +1010,8 @@ void NaviCubeImplementation::handleResize() { void NaviCubeImplementation::drawNaviCube(bool pickMode) { // initializes stuff here when we actually have a context - // FIXME actually now that we have Qt5, we could probably do this earlier (as we do not need the opengl context) + // FIXME actually now that we have Qt5, we could probably do this earlier + // (as we do not need the opengl context) if (!m_NaviCubeInitialised) { auto gl = static_cast(m_View3DInventorViewer->viewport()); if (!gl) @@ -1060,7 +1108,8 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode) { if (!pickMode) { // Draw the axes - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/NaviCube"); + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/NaviCube"); bool ShowCS = hGrp->GetBool("ShowCS", 1); if (ShowCS) { glDisable(GL_TEXTURE_2D); @@ -1103,8 +1152,8 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode) { for (int pass = 0; pass < 3; pass++) { for (vector::iterator f = m_Faces.begin(); f != m_Faces.end(); f++) { //if (pickMode) { // pick should not be drawn in tree passes - // glColor3ub((*f)->m_PickId, 0, 0); - // glBindTexture(GL_TEXTURE_2D, (*f)->m_PickTextureId); + // glColor3ub((*f)->m_PickId, 0, 0); + // glBindTexture(GL_TEXTURE_2D, (*f)->m_PickTextureId); //} else { if (pass != (*f)->m_RenderPass) continue; @@ -1132,7 +1181,8 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode) { if (pass != f->m_RenderPass) continue; if (f->m_TextureId == f->m_PickTextureId) { - if (f->m_PickTexId == TEX_FRONT_FACE || f->m_PickTexId == TEX_EDGE_FACE || f->m_PickTexId == TEX_CORNER_FACE) { + if (f->m_PickTexId == TEX_FRONT_FACE || f->m_PickTexId == TEX_EDGE_FACE + || f->m_PickTexId == TEX_CORNER_FACE) { glBegin(GL_POLYGON); for (const Vector3f& v : m_VertexArrays2[f->m_PickId]) { glVertex3f(v[0], v[1], v[2]); @@ -1730,7 +1780,6 @@ bool NaviCubeImplementation::processSoEvent(const SoEvent* ev) { return false; } - QString NaviCubeImplementation::str(const char* str) { return QString::fromLatin1(str); } @@ -1745,8 +1794,6 @@ void NaviCube::setNaviCubeLabels(const std::vector& labels) NaviCubeImplementation::m_labels = labels; } - - DEF_3DV_CMD(ViewIsometricCmd) ViewIsometricCmd::ViewIsometricCmd() : Command("ViewIsometricCmd") diff --git a/src/Gui/NaviCube.h b/src/Gui/NaviCube.h index a55d71672c..2dde73f6a9 100644 --- a/src/Gui/NaviCube.h +++ b/src/Gui/NaviCube.h @@ -41,22 +41,18 @@ public: BottomLeftCorner, BottomRightCorner }; - NaviCube(Gui::View3DInventorViewer* viewer) ; + NaviCube(Gui::View3DInventorViewer* viewer); virtual ~NaviCube(); void drawNaviCube(); void createContextMenu(const std::vector& cmd); bool processSoEvent(const SoEvent* ev); void setCorner(Corner); + static QFont getDefaultSansserifFont(); static void setNaviCubeCommands(const std::vector& cmd); static void setNaviCubeLabels(const std::vector& labels); + private: NaviCubeImplementation* m_NaviCubeImplementation; }; -class HuuhaaClassPy : public Py::PythonExtension { -public: - Py::Object huuhaa(const Py::Tuple&); - static void init_type() ; -}; - #endif /* SRC_GUI_NAVICUBE_H_ */ diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index ebbd583cfd..4ef4fd653f 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1176,6 +1176,23 @@ NaviCube* View3DInventorViewer::getNavigationCube() const return naviCube; } +void View3DInventorViewer::createNavigationCube() +{ + if (!naviCube) { + naviCube = new NaviCube(this); + naviCubeEnabled = true; + } +} + +void View3DInventorViewer::deleteNavigationCube() +{ + if (naviCube) { + delete naviCube; + naviCube = nullptr; + naviCubeEnabled = false; + } +} + void View3DInventorViewer::setAxisCross(bool on) { SoNode* scene = getSceneGraph(); diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index ea952d806b..bb5a7881cb 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -387,6 +387,8 @@ public: bool isEnabledNaviCube() const; void setNaviCubeCorner(int); NaviCube* getNavigationCube() const; + void createNavigationCube(); + void deleteNavigationCube(); void setEnabledVBO(bool b); bool isEnabledVBO() const; void setRenderCache(int);