fix(gui): UI appearance polish — Wayland scaling, menu icon size pref, dialog cleanup
Some checks failed
Build and Test / build (pull_request) Failing after 13m13s

- Fix hazy text on Wayland by setting QT_SCALE_FACTOR_ROUNDING_POLICY=RoundPreferFloor
  and QT_ENABLE_HIGHDPI_SCALING=1 in deb and AppImage launchers; remove forced
  QT_QPA_PLATFORM=xcb from AppImage to allow native Wayland (fixes #33)

- Add menu icon size preference selector (Small/Medium/Large/Extra large) in
  General preferences, applied via QMenu stylesheet at startup and on save (fixes #46)

- Replace verbose theme customization banner with concise 'Kindred Create Theme'
  label in UI preferences; split Overlay group into 'Panel Visibility' and
  'Overlay Interaction' sections (fixes #35)

- Remove Addon Manager branding label from General preferences, change recent
  file list default from 4 to 10 (fixes #36)
This commit is contained in:
forbes
2026-02-08 13:27:22 -06:00
parent be7f1d9221
commit cc5ba638d1
8 changed files with 144 additions and 72 deletions

View File

@@ -112,6 +112,10 @@ export XKB_CONFIG_ROOT="${KINDRED_CREATE_HOME}/share/X11/xkb"
export FONTCONFIG_FILE="${KINDRED_CREATE_HOME}/etc/fonts/fonts.conf" export FONTCONFIG_FILE="${KINDRED_CREATE_HOME}/etc/fonts/fonts.conf"
export FONTCONFIG_PATH="${KINDRED_CREATE_HOME}/etc/fonts" export FONTCONFIG_PATH="${KINDRED_CREATE_HOME}/etc/fonts"
# Qt Wayland fractional scaling — force integer rounding to avoid blurry text
export QT_SCALE_FACTOR_ROUNDING_POLICY=RoundPreferFloor
export QT_ENABLE_HIGHDPI_SCALING=1
# Use system CA certificates so bundled Python trusts internal CAs (e.g. FreeIPA) # Use system CA certificates so bundled Python trusts internal CAs (e.g. FreeIPA)
# The bundled openssl has a hardcoded cafile from the build environment which # The bundled openssl has a hardcoded cafile from the build environment which
# does not exist on the target system. # does not exist on the target system.

View File

@@ -9,8 +9,9 @@ export PATH_TO_FREECAD_LIBDIR=${HERE}/usr/lib
export FONTCONFIG_FILE=/etc/fonts/fonts.conf export FONTCONFIG_FILE=/etc/fonts/fonts.conf
export FONTCONFIG_PATH=/etc/fonts export FONTCONFIG_PATH=/etc/fonts
# Fix: Use X to run on Wayland # Qt HiDPI scaling — force integer rounding to avoid blurry text on fractional scales
export QT_QPA_PLATFORM=xcb export QT_SCALE_FACTOR_ROUNDING_POLICY=RoundPreferFloor
export QT_ENABLE_HIGHDPI_SCALING=1
# Show packages info if DEBUG env variable is set # Show packages info if DEBUG env variable is set
if [ "$DEBUG" = 1 ]; then if [ "$DEBUG" = 1 ]; then

View File

@@ -28,6 +28,7 @@
#include <QApplication> #include <QApplication>
#include <QFileDialog> #include <QFileDialog>
#include <QLocale> #include <QLocale>
#include <QMenu>
#include <QMessageBox> #include <QMessageBox>
#include <QString> #include <QString>
#include <algorithm> #include <algorithm>
@@ -96,7 +97,6 @@ DlgSettingsGeneral::DlgSettingsGeneral(QWidget* parent)
ui->SaveNewPreferencePack->setEnabled(false); ui->SaveNewPreferencePack->setEnabled(false);
ui->ManagePreferencePacks->setEnabled(false); ui->ManagePreferencePacks->setEnabled(false);
ui->themesCombobox->setEnabled(false); ui->themesCombobox->setEnabled(false);
ui->moreThemesLabel->setEnabled(false);
} }
} }
} }
@@ -121,7 +121,6 @@ DlgSettingsGeneral::DlgSettingsGeneral(QWidget* parent)
this, this,
&DlgSettingsGeneral::onThemeChanged &DlgSettingsGeneral::onThemeChanged
); );
connect(ui->moreThemesLabel, &QLabel::linkActivated, this, &DlgSettingsGeneral::onLinkActivated);
} }
// If there are any saved config file backs, show the revert button, otherwise hide it: // If there are any saved config file backs, show the revert button, otherwise hide it:
@@ -147,9 +146,6 @@ DlgSettingsGeneral::DlgSettingsGeneral(QWidget* parent)
const auto visible = UnitsApi::isMultiUnitLength(); const auto visible = UnitsApi::isMultiUnitLength();
ui->comboBox_FracInch->setVisible(visible); ui->comboBox_FracInch->setVisible(visible);
ui->fractionalInchLabel->setVisible(visible); ui->fractionalInchLabel->setVisible(visible);
ui->moreThemesLabel->setEnabled(
Application::Instance->commandManager().getCommandByName("Std_AddonMgr") != nullptr
);
} }
/** /**
@@ -166,7 +162,7 @@ void DlgSettingsGeneral::setRecentFileSize()
auto recent = getMainWindow()->findChild<RecentFilesAction*>(QLatin1String("recentFiles")); auto recent = getMainWindow()->findChild<RecentFilesAction*>(QLatin1String("recentFiles"));
if (recent) { if (recent) {
ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("RecentFiles"); ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("RecentFiles");
recent->resizeList(hGrp->GetInt("RecentFiles", 4)); recent->resizeList(hGrp->GetInt("RecentFiles", 10));
} }
} }
@@ -264,6 +260,11 @@ void DlgSettingsGeneral::saveSettings()
hGrp->SetInt("ToolbarIconSize", pixel); hGrp->SetInt("ToolbarIconSize", pixel);
getMainWindow()->setIconSize(QSize(pixel, pixel)); getMainWindow()->setIconSize(QSize(pixel, pixel));
QVariant menuSize = ui->menuIconSize->itemData(ui->menuIconSize->currentIndex());
int menuPixel = menuSize.toInt();
hGrp->SetInt("MenuIconSize", menuPixel);
applyMenuIconSize(menuPixel);
int blinkTime {hGrp->GetBool("EnableCursorBlinking", true) ? -1 : 0}; int blinkTime {hGrp->GetBool("EnableCursorBlinking", true) ? -1 : 0};
qApp->setCursorFlashTime(blinkTime); qApp->setCursorFlashTime(blinkTime);
@@ -348,6 +349,7 @@ void DlgSettingsGeneral::loadSettings()
} }
addIconSizes(getCurrentIconSize()); addIconSizes(getCurrentIconSize());
addMenuIconSizes(getCurrentMenuIconSize());
// TreeMode combobox setup. // TreeMode combobox setup.
loadDockWindowVisibility(); loadDockWindowVisibility();
@@ -395,8 +397,9 @@ void DlgSettingsGeneral::resetSettingsToDefaults()
hGrp = WindowParameter::getDefaultParameter()->GetGroup("General"); hGrp = WindowParameter::getDefaultParameter()->GetGroup("General");
// reset "Language" parameter // reset "Language" parameter
hGrp->RemoveASCII("Language"); hGrp->RemoveASCII("Language");
// reset "ToolbarIconSize" parameter // reset "ToolbarIconSize" and "MenuIconSize" parameters
hGrp->RemoveInt("ToolbarIconSize"); hGrp->RemoveInt("ToolbarIconSize");
hGrp->RemoveInt("MenuIconSize");
// finally reset all the parameters associated to Gui::Pref* widgets // finally reset all the parameters associated to Gui::Pref* widgets
PreferencePage::resetSettingsToDefaults(); PreferencePage::resetSettingsToDefaults();
@@ -534,6 +537,63 @@ void DlgSettingsGeneral::translateIconSizes()
} }
} }
int DlgSettingsGeneral::getCurrentMenuIconSize() const
{
ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("General");
return hGrp->GetInt("MenuIconSize", 24);
}
void DlgSettingsGeneral::addMenuIconSizes(int current)
{
ui->menuIconSize->clear();
QList<int> sizes {16, 20, 24, 28};
if (!sizes.contains(current)) {
sizes.append(current);
}
for (int size : sizes) {
ui->menuIconSize->addItem(QString(), QVariant(size));
}
int index = ui->menuIconSize->findData(QVariant(current));
ui->menuIconSize->setCurrentIndex(index);
translateMenuIconSizes();
}
void DlgSettingsGeneral::translateMenuIconSizes()
{
auto getSize = [this](int index) {
return ui->menuIconSize->itemData(index).toInt();
};
QStringList sizes;
sizes << tr("Small (%1px)").arg(getSize(0));
sizes << tr("Medium (%1px)").arg(getSize(1));
sizes << tr("Large (%1px)").arg(getSize(2));
sizes << tr("Extra large (%1px)").arg(getSize(3));
if (ui->menuIconSize->count() > 4) {
sizes << tr("Custom (%1px)").arg(getSize(4));
}
for (int index = 0; index < sizes.size(); index++) {
ui->menuIconSize->setItemText(index, sizes[index]);
}
}
void DlgSettingsGeneral::applyMenuIconSize(int pixel)
{
// Apply menu icon size via stylesheet override on all QMenu widgets
QString rule = QStringLiteral("QMenu::icon { width: %1px; height: %1px; }").arg(pixel);
for (auto* widget : qApp->allWidgets()) {
if (auto* menu = qobject_cast<QMenu*>(widget)) {
menu->setStyleSheet(rule);
}
}
// Store the rule so new menus pick it up via the main window
getMainWindow()->setProperty("_menuIconSizeRule", rule);
}
void DlgSettingsGeneral::retranslateUnits() void DlgSettingsGeneral::retranslateUnits()
{ {
auto setItem = [&, index {0}](const std::string& item) mutable { auto setItem = [&, index {0}](const std::string& item) mutable {
@@ -547,6 +607,7 @@ void DlgSettingsGeneral::changeEvent(QEvent* event)
{ {
if (event->type() == QEvent::LanguageChange) { if (event->type() == QEvent::LanguageChange) {
translateIconSizes(); translateIconSizes();
translateMenuIconSizes();
retranslateUnits(); retranslateUnits();
int index = ui->UseLocaleFormatting->currentIndex(); int index = ui->UseLocaleFormatting->currentIndex();
ui->retranslateUi(this); ui->retranslateUi(this);
@@ -823,24 +884,6 @@ void DlgSettingsGeneral::onThemeChanged(int index)
themeChanged = true; themeChanged = true;
} }
void DlgSettingsGeneral::onLinkActivated(const QString& link)
{
auto const addonManagerLink = QStringLiteral("freecad:Std_AddonMgr");
if (link != addonManagerLink) {
return;
}
// Set the user preferences to include only preference packs.
// This is a quick and dirty way to open Addon Manager with only themes.
auto pref = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Addons"
);
pref->SetInt("PackageTypeSelection", 3); // 3 stands for Preference Packs
pref->SetInt("StatusSelection", 0); // 0 stands for any installation status
Gui::Application::Instance->commandManager().runCommandByName("Std_AddonMgr");
}
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
namespace namespace

View File

@@ -72,7 +72,6 @@ protected Q_SLOTS:
void onManagePreferencePacksClicked(); void onManagePreferencePacksClicked();
void onImportConfigClicked(); void onImportConfigClicked();
void onThemeChanged(int index); void onThemeChanged(int index);
void onLinkActivated(const QString& link);
public Q_SLOTS: public Q_SLOTS:
void onUnitSystemIndexChanged(int index); void onUnitSystemIndexChanged(int index);
@@ -91,6 +90,10 @@ private:
int getCurrentIconSize() const; int getCurrentIconSize() const;
void addIconSizes(int current); void addIconSizes(int current);
void translateIconSizes(); void translateIconSizes();
int getCurrentMenuIconSize() const;
void addMenuIconSizes(int current);
void translateMenuIconSizes();
static void applyMenuIconSize(int pixel);
private: private:
int localeIndex; int localeIndex;

View File

@@ -219,35 +219,35 @@ dot/period will always be printed</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="moreThemesLabel"> <item row="1" column="0">
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string>Looking for more themes? You can obtain them using the &lt;a href=&quot;freecad:Std_AddonMgr&quot;&gt;Addon Manager&lt;/a&gt;.</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="iconSizeLabel"> <widget class="QLabel" name="iconSizeLabel">
<property name="text"> <property name="text">
<string>Size of toolbar icons</string> <string>Size of toolbar icons</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="1" column="1">
<widget class="QComboBox" name="toolbarIconSize"> <widget class="QComboBox" name="toolbarIconSize">
<property name="toolTip"> <property name="toolTip">
<string>Icon size in the toolbar</string> <string>Icon size in the toolbar</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="menuIconSizeLabel">
<property name="text">
<string>Size of menu icons</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="menuIconSize">
<property name="toolTip">
<string>Icon size in context menus and dropdown menus</string>
</property>
</widget>
</item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="treeModeLabel"> <widget class="QLabel" name="treeModeLabel">
<property name="text"> <property name="text">
@@ -278,7 +278,7 @@ dot/period will always be printed</string>
<string>How many files should be listed in recent files list</string> <string>How many files should be listed in recent files list</string>
</property> </property>
<property name="value"> <property name="value">
<number>4</number> <number>10</number>
</property> </property>
<property name="prefEntry" stdset="0"> <property name="prefEntry" stdset="0">
<cstring>RecentFiles</cstring> <cstring>RecentFiles</cstring>

View File

@@ -23,7 +23,7 @@
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Customize the current theme. The offered settings are optional for theme developers so they may or may not have an effect in the current theme.</string> <string>Kindred Create Theme</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
@@ -392,10 +392,10 @@
<item> <item>
<widget class="QGroupBox" name="groupBox_3"> <widget class="QGroupBox" name="groupBox_3">
<property name="title"> <property name="title">
<string>Overlay</string> <string>Panel Visibility</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="0"> <item row="0" column="0">
<widget class="Gui::PrefCheckBox" name="hideTabBarCheckBox"> <widget class="Gui::PrefCheckBox" name="hideTabBarCheckBox">
<property name="toolTip"> <property name="toolTip">
<string>Hide tab bar in dock overlay</string> <string>Hide tab bar in dock overlay</string>
@@ -414,23 +414,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="1" column="0">
<widget class="Gui::PrefCheckBox" name="hintShowTabBarCheckBox">
<property name="toolTip">
<string>Show tab bar on mouse over when auto hide</string>
</property>
<property name="text">
<string>Hint show tab bar</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>DockOverlayHintTabBar</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>View</cstring>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="Gui::PrefCheckBox" name="hidePropertyViewScrollBarCheckBox"> <widget class="Gui::PrefCheckBox" name="hidePropertyViewScrollBarCheckBox">
<property name="toolTip"> <property name="toolTip">
<string>Hide property view scroll bar in dock overlay</string> <string>Hide property view scroll bar in dock overlay</string>
@@ -446,7 +430,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0"> <item row="2" column="0">
<widget class="Gui::PrefCheckBox" name="overlayAutoHideCheckBox"> <widget class="Gui::PrefCheckBox" name="overlayAutoHideCheckBox">
<property name="toolTip"> <property name="toolTip">
<string>Automatically hide overlaid dock panels when in non 3D view (e.g. TechDraw or Spreadsheet)</string> <string>Automatically hide overlaid dock panels when in non 3D view (e.g. TechDraw or Spreadsheet)</string>
@@ -465,13 +449,22 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="0"> </layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3b">
<property name="title">
<string>Overlay Interaction</string>
</property>
<layout class="QGridLayout" name="gridLayout_2b">
<item row="0" column="0">
<widget class="Gui::PrefCheckBox" name="mouseClickPassThroughCheckBox"> <widget class="Gui::PrefCheckBox" name="mouseClickPassThroughCheckBox">
<property name="toolTip"> <property name="toolTip">
<string>Auto mouse click through transparent part of dock overlay.</string> <string>Auto mouse click through transparent part of dock overlay</string>
</property> </property>
<property name="text"> <property name="text">
<string>Automatically pass through of the mouse cursor</string> <string>Automatically pass through mouse cursor</string>
</property> </property>
<property name="checked"> <property name="checked">
<bool>true</bool> <bool>true</bool>
@@ -484,13 +477,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="0"> <item row="1" column="0">
<widget class="Gui::PrefCheckBox" name="mouseWheelPassThroughCheckBox"> <widget class="Gui::PrefCheckBox" name="mouseWheelPassThroughCheckBox">
<property name="toolTip"> <property name="toolTip">
<string>Automatically passes mouse wheel events through the transparent areas of an overlay panel</string> <string>Automatically passes mouse wheel events through the transparent areas of an overlay panel</string>
</property> </property>
<property name="text"> <property name="text">
<string>Automatically pass through of the mouse wheel</string> <string>Automatically pass through mouse wheel</string>
</property> </property>
<property name="checked"> <property name="checked">
<bool>true</bool> <bool>true</bool>
@@ -503,6 +496,22 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="Gui::PrefCheckBox" name="hintShowTabBarCheckBox">
<property name="toolTip">
<string>Show tab bar on mouse over when auto hide</string>
</property>
<property name="text">
<string>Hint show tab bar</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>DockOverlayHintTabBar</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>View</cstring>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@@ -56,6 +56,7 @@
#include "Language/Translator.h" #include "Language/Translator.h"
#include "Dialogs/DlgVersionMigrator.h" #include "Dialogs/DlgVersionMigrator.h"
#include "FreeCADStyle.h" #include "FreeCADStyle.h"
#include "PreferencePages/DlgSettingsGeneral.h"
#include <App/Application.h> #include <App/Application.h>
#include <Base/Console.h> #include <Base/Console.h>
@@ -226,6 +227,7 @@ void StartupPostProcess::execute()
setProcessMessages(); setProcessMessages();
setAutoSaving(); setAutoSaving();
setToolBarIconSize(); setToolBarIconSize();
setMenuIconSize();
setWheelEventFilter(); setWheelEventFilter();
setLocale(); setLocale();
setCursorFlashing(); setCursorFlashing();
@@ -281,6 +283,15 @@ void StartupPostProcess::setToolBarIconSize()
} }
} }
void StartupPostProcess::setMenuIconSize()
{
ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("General");
int size = int(hGrp->GetInt("MenuIconSize", 0));
if (size >= 16) {
DlgSettingsGeneral::applyMenuIconSize(size);
}
}
void StartupPostProcess::setWheelEventFilter() void StartupPostProcess::setWheelEventFilter()
{ {
// filter wheel events for combo boxes // filter wheel events for combo boxes

View File

@@ -64,6 +64,7 @@ private:
void setProcessMessages(); void setProcessMessages();
void setAutoSaving(); void setAutoSaving();
void setToolBarIconSize(); void setToolBarIconSize();
void setMenuIconSize();
void setWheelEventFilter(); void setWheelEventFilter();
void setLocale(); void setLocale();
void setCursorFlashing(); void setCursorFlashing();