From 588f2d50e4e108299a754e5c229cdc396342d2dd Mon Sep 17 00:00:00 2001 From: Uwe Date: Fri, 20 Jan 2023 07:10:57 +0100 Subject: [PATCH] [Gui] allow to specify font for NaviCube - the problem is that depending on the OS, the font of the NaviCube is hardly readable. For example under Windows 11, there is no Helvetica font and therefore an ugly replacement font is used. On some laptop screens the font is too large or too small etc. - as solution this PR add the change the NaviCube's font and font size - the PR also fixes an issue that the position (corner) of the NaviCube was not respected when the NaviCube is recreated. This fix is necessary for the PR therefore included - as by-product the PR fixes #8082 since every change in the preferences now properly recreates the NaviCube - the PR also removes the strange and unused class "HuuhaaClassPy" --- src/Gui/DlgSettingsNavigation.cpp | 46 +++++++++++-- src/Gui/DlgSettingsNavigation.ui | 71 ++++++++++++++++++-- src/Gui/NaviCube.cpp | 103 ++++++++++++++++++++++-------- src/Gui/NaviCube.h | 10 +-- src/Gui/View3DInventorViewer.cpp | 17 +++++ src/Gui/View3DInventorViewer.h | 2 + 6 files changed, 205 insertions(+), 44 deletions(-) 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);