View Issue Details

IDProjectCategoryView StatusLast Update
0017571ScribusUser Interfacepublic2025-10-22 22:21
Reporternitramr Assigned Tonitramr  
PrioritynormalSeverityfeatureReproducibilityN/A
Status assignedResolutionopen 
PlatformDesktop PCOSUbuntuOS Version24.10 64-bit
Product Version1.7.1.svn 
Target Version1.7 milestone 
Summary0017571: Add button group ui widget
DescriptionI created a custom button group widget that assigns a proxy style to all tool buttons within the button group. The new style looks like a real visual group.

I also replaced some UI button groups with the new one.

Button group features
- Based on QButtonGroup
- All added buttons are automatically styled.
- When a button is added, deleted, or its visibility is changed, the button style of all buttons is regenerated.

Tested un Ubuntu (dark + light theme) and MacOS (light theme)
TagsNo tags attached.
Attached Files
buttongroup_2025-07-04_01.patch (19,671 bytes)   
diff --git a/scribus/CMakeLists_Sources.txt b/scribus/CMakeLists_Sources.txt
index 35422ba..cdb62da 100644
--- a/scribus/CMakeLists_Sources.txt
+++ b/scribus/CMakeLists_Sources.txt
@@ -561,6 +561,7 @@ set(SCRIBUS_SOURCES
 	ui/delegates/sclistitemdelegate.cpp
 	ui/docks/dock_centralwidget.cpp
 	ui/docks/dock_panelbase.cpp
+	ui/widgets/buttongroup.cpp
 	ui/widgets/color_button.cpp
 	ui/widgets/color_slider.cpp
 	ui/widgets/combo_blendmode.cpp
diff --git a/scribus/ui/propertiespalette_shape.cpp b/scribus/ui/propertiespalette_shape.cpp
index 0dcbd21..4414a23 100644
--- a/scribus/ui/propertiespalette_shape.cpp
+++ b/scribus/ui/propertiespalette_shape.cpp
@@ -25,6 +25,7 @@ for which a new license (GPL+exception) is in place.
 #include "scribusview.h"
 #include "selection.h"
 #include "units.h"
+#include "ui/widgets/buttongroup.h"
 
 PropertiesPalette_Shape::PropertiesPalette_Shape( QWidget* parent)
 	: QWidget(parent)
@@ -45,6 +46,13 @@ PropertiesPalette_Shape::PropertiesPalette_Shape( QWidget* parent)
 	textFlowMargins->toggleLabelVisibility(false);
 	textFlowMargins->setLinkValues(true);
 
+	ButtonGroup * bgFlow = new ButtonGroup();
+	bgFlow->addButton(textFlowDisabled);
+	bgFlow->addButton(textFlowUsesBoundingBox);
+	bgFlow->addButton(textFlowUsesContourLine);
+	bgFlow->addButton(textFlowUsesFrameShape);
+	bgFlow->addButton(textFlowUsesImageClipping);
+
 	connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
 	connect(ScQApp, SIGNAL(localeChanged()), this, SLOT(localeChange()));
 	connect(ScQApp, SIGNAL(labelVisibilityChanged(bool)), this, SLOT(toggleLabelVisibility(bool)));
diff --git a/scribus/ui/alignselect.cpp b/scribus/ui/alignselect.cpp
index 725617a..c2c1968 100644
--- a/scribus/ui/alignselect.cpp
+++ b/scribus/ui/alignselect.cpp
@@ -16,7 +16,7 @@ for which a new license (GPL+exception) is in place.
 
 AlignSelect::AlignSelect(QWidget* parent) : FormWidget(parent)
 {
-	buttonGroup = new QButtonGroup(this);
+	buttonGroup = new ButtonGroup(this);
 
 	TextL = new QToolButton( this );
 	TextL->setCheckable( true );
@@ -45,6 +45,9 @@ AlignSelect::AlignSelect(QWidget* parent) : FormWidget(parent)
 	addWidget(TextB);
 	addWidget(TextF);
 
+	// Modifiy layout spacing. Layout is created by addWidget()
+	layout()->setSpacing(0);
+
 	iconSetChange();
 	languageChange();
 
diff --git a/scribus/ui/alignselect.h b/scribus/ui/alignselect.h
index 9bd60ff..54efb0c 100644
--- a/scribus/ui/alignselect.h
+++ b/scribus/ui/alignselect.h
@@ -14,6 +14,7 @@ for which a new license (GPL+exception) is in place.
 class QEvent;
 
 #include "scribusapi.h"
+#include "ui/widgets/buttongroup.h"
 #include "ui/widgets/form_widget.h"
 
 class SCRIBUS_API AlignSelect : public FormWidget
@@ -30,7 +31,7 @@ public:
 	int selectedId() const;
 
 	int selected { 0 };
-	QButtonGroup* buttonGroup { nullptr };
+	ButtonGroup* buttonGroup { nullptr };
 	QToolButton* TextL { nullptr };
 	QToolButton* TextR { nullptr };
 	QToolButton* TextC { nullptr };
diff --git a/scribus/ui/alignverticalselect.cpp b/scribus/ui/alignverticalselect.cpp
index 13a6234..f88d511 100644
--- a/scribus/ui/alignverticalselect.cpp
+++ b/scribus/ui/alignverticalselect.cpp
@@ -16,7 +16,7 @@ for which a new license (GPL+exception) is in place.
 
 AlignVerticalSelect::AlignVerticalSelect(QWidget* parent) : FormWidget(parent)
 {
-	buttonGroup = new QButtonGroup(this);
+	buttonGroup = new ButtonGroup(this);
 	buttonGroup->setExclusive(true);
 
 	TextT = new QToolButton( this );
@@ -36,6 +36,9 @@ AlignVerticalSelect::AlignVerticalSelect(QWidget* parent) : FormWidget(parent)
 	addWidget(TextC);
 	addWidget(TextB);
 
+	// Modifiy layout spacing. Layout is created by addWidget()
+	layout()->setSpacing(0);
+
 	iconSetChange();
 	languageChange();
 
diff --git a/scribus/ui/alignverticalselect.h b/scribus/ui/alignverticalselect.h
index 4a5d6b0..02782ed 100644
--- a/scribus/ui/alignverticalselect.h
+++ b/scribus/ui/alignverticalselect.h
@@ -14,6 +14,7 @@ for which a new license (GPL+exception) is in place.
 class QEvent;
 
 #include "scribusapi.h"
+#include "ui/widgets/buttongroup.h"
 #include "ui/widgets/form_widget.h"
 
 class SCRIBUS_API AlignVerticalSelect : public FormWidget
@@ -28,7 +29,7 @@ public:
 	void setStyle(int s);
 	int getStyle() const;
 
-	QButtonGroup* buttonGroup { nullptr };
+	ButtonGroup* buttonGroup { nullptr };
 	QToolButton* TextT { nullptr };
 	QToolButton* TextC { nullptr };
 	QToolButton* TextB { nullptr };
diff --git a/scribus/ui/directionselect.cpp b/scribus/ui/directionselect.cpp
index 24556ec..5d0aa59 100644
--- a/scribus/ui/directionselect.cpp
+++ b/scribus/ui/directionselect.cpp
@@ -15,7 +15,13 @@ for which a new license (GPL+exception) is in place.
 
 DirectionSelect::DirectionSelect(QWidget* parent) : FormWidget(parent)
 {
-	buttonGroup = new QButtonGroup(this);
+	buttonGroup = new ButtonGroup(this);
+
+	QHBoxLayout* lay = new QHBoxLayout();
+	lay->setContentsMargins(0, 0, 0, 0);
+	lay->setSpacing(0);
+	lay->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
+	setLayout(lay);
 
 	LTR = new QToolButton( this );
 	LTR->setCheckable( true );
@@ -28,11 +34,13 @@ DirectionSelect::DirectionSelect(QWidget* parent) : FormWidget(parent)
 	addWidget( RTL );
 	buttonGroup->addButton(RTL, 1);
 
-	resize(minimumSizeHint());
+	lay->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
 
 	iconSetChange();
 	languageChange();
 
+	resize(minimumSizeHint());
+
 	connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
 	connect(buttonGroup, SIGNAL(idClicked(int)), this, SLOT(setTypeStyle(int)));
 }
diff --git a/scribus/ui/directionselect.h b/scribus/ui/directionselect.h
index 3d69cd6..23ad6c2 100644
--- a/scribus/ui/directionselect.h
+++ b/scribus/ui/directionselect.h
@@ -16,6 +16,7 @@ for which a new license (GPL+exception) is in place.
 class QEvent;
 
 #include "scribusapi.h"
+#include "ui/widgets/buttongroup.h"
 #include "ui/widgets/form_widget.h"
 
 class SCRIBUS_API DirectionSelect : public FormWidget
@@ -30,7 +31,7 @@ class SCRIBUS_API DirectionSelect : public FormWidget
 		int getStyle();
 		int selectedId();
 
-		QButtonGroup* buttonGroup { nullptr };
+		ButtonGroup* buttonGroup { nullptr };
 		QToolButton* RTL { nullptr };
 		QToolButton* LTR { nullptr };
 
diff --git a/scribus/ui/flopwidget.cpp b/scribus/ui/flopwidget.cpp
index 0b3a537..f5e2d94 100644
--- a/scribus/ui/flopwidget.cpp
+++ b/scribus/ui/flopwidget.cpp
@@ -23,10 +23,10 @@ FlopWidget::FlopWidget(QWidget* parent) : FormWidget(parent)
 	flopBaselineGrid = new QToolButton();
 	flopBaselineGrid->setCheckable(true);
 
-	flopGroup = new QButtonGroup();
+	flopGroup = new ButtonGroup();
 	flopGroup->setExclusive(true);
-	flopGroup->addButton(flopRealHeight,  RealHeightID);
 	flopGroup->addButton(flopFontAscent,  FontAscentID);
+	flopGroup->addButton(flopRealHeight,  RealHeightID);
 	flopGroup->addButton(flopLineSpacing, LineSpacingID);
 	flopGroup->addButton(flopBaselineGrid, BaselineGridID);
 
@@ -35,6 +35,9 @@ FlopWidget::FlopWidget(QWidget* parent) : FormWidget(parent)
 	addWidget(flopLineSpacing);
 	addWidget(flopBaselineGrid);
 
+	// Modifiy layout spacing. Layout is created by addWidget()
+	layout()->setSpacing(0);
+
 	iconSetChange();
 	languageChange();
 
diff --git a/scribus/ui/flopwidget.h b/scribus/ui/flopwidget.h
index cdb682d..d312cbf 100644
--- a/scribus/ui/flopwidget.h
+++ b/scribus/ui/flopwidget.h
@@ -9,7 +9,9 @@ for which a new license (GPL+exception) is in place.
 
 
 #include <QButtonGroup>
+#include <QHBoxLayout>
 #include <QToolButton>
+#include "ui/widgets/buttongroup.h"
 #include "ui/widgets/form_widget.h"
 
 class ScribusDoc;
@@ -31,7 +33,7 @@ public:
 	FlopWidget(QWidget* parent);
 	~FlopWidget() {};
 
-	QButtonGroup *flopGroup;
+	ButtonGroup *flopGroup;
 	QToolButton *flopRealHeight = {nullptr};
 	QToolButton *flopFontAscent = {nullptr};
 	QToolButton *flopLineSpacing = {nullptr};
diff --git a/scribus/ui/newdocdialog.cpp b/scribus/ui/newdocdialog.cpp
index c71ef70..9b14b16 100644
--- a/scribus/ui/newdocdialog.cpp
+++ b/scribus/ui/newdocdialog.cpp
@@ -142,12 +142,12 @@ void NewDocDialog::createNewDocPage()
 	comboSortSizes->addItem( tr("Size Desc"), PageSizeList::DimensionDesc);
 	comboSortSizes->setCurrentIndex(0);
 
-	pageOrientationButtons = new QButtonGroup();
+	pageOrientationButtons = new ButtonGroup();
 	pageOrientationButtons->addButton(buttonVertical, 0);
 	pageOrientationButtons->addButton(buttonHorizontal, 1);
 	pageOrientationButtons->button(orientation)->setChecked(true);
 
-	pageLayoutButtons = new QButtonGroup();
+	pageLayoutButtons = new ButtonGroup();
 	pageLayoutButtons->addButton(buttonSinglePage, 0);
 	pageLayoutButtons->addButton(buttonDoublePageLeft, 1);
 	pageLayoutButtons->addButton(buttonDoublePageRight, 2);
diff --git a/scribus/ui/newdocdialog.h b/scribus/ui/newdocdialog.h
index 50e9c95..6d7b962 100644
--- a/scribus/ui/newdocdialog.h
+++ b/scribus/ui/newdocdialog.h
@@ -34,6 +34,7 @@ class QSpinBox;
 #include "scribusstructs.h"
 #include "ui/customfdialog.h"
 #include "ui/nftwidget.h"
+#include "ui/widgets/buttongroup.h"
 
 #include "ui_newdocdialog.h"
 
@@ -119,8 +120,8 @@ private slots:
 protected:
 	PrefsManager& prefsManager;
 	QStringList recentDocList;
-	QButtonGroup* pageOrientationButtons;
-	QButtonGroup* pageLayoutButtons;
+	ButtonGroup* pageOrientationButtons;
+	ButtonGroup* pageLayoutButtons;
 
 	double m_unitRatio { 1.0 };
 	int m_orientation { 0 };
diff --git a/scribus/ui/propertiespalette_fill.cpp b/scribus/ui/propertiespalette_fill.cpp
index 7b7fc45..a5e425f 100644
--- a/scribus/ui/propertiespalette_fill.cpp
+++ b/scribus/ui/propertiespalette_fill.cpp
@@ -8,6 +8,7 @@
 #include "selection.h"
 #include "undomanager.h"
 #include "ui/colorpicker/colorpicker.h"
+#include "ui/widgets/buttongroup.h"
 
 PropertiesPalette_Fill::PropertiesPalette_Fill(QWidget *parent) :
 	QWidget(parent)
@@ -23,6 +24,10 @@ PropertiesPalette_Fill::PropertiesPalette_Fill(QWidget *parent) :
 
 	undoManager = UndoManager::instance();
 
+	ButtonGroup * fillRuleGroup = new ButtonGroup();
+	fillRuleGroup->addButton(evenOdd);
+	fillRuleGroup->addButton(nonZero);
+
 	iconSetChange();
 	languageChange();
 
diff --git a/scribus/ui/propertiespalette_line.cpp b/scribus/ui/propertiespalette_line.cpp
index 40060b2..e8bacf7 100644
--- a/scribus/ui/propertiespalette_line.cpp
+++ b/scribus/ui/propertiespalette_line.cpp
@@ -39,15 +39,15 @@ PropertiesPalette_Line::PropertiesPalette_Line( QWidget* parent) : QWidget(paren
 	setupUi(this);
 	setSizePolicy( QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum));
 
-	buttonsCaps = new QButtonGroup();
+	buttonsCaps = new ButtonGroup();
 	buttonsCaps->addButton(buttonCapFlat, 0);
 	buttonsCaps->addButton(buttonCapSquare, 1);
 	buttonsCaps->addButton(buttonCapRound, 2);
 
-	buttonsJoins = new QButtonGroup();
+	buttonsJoins = new ButtonGroup();
 	buttonsJoins->addButton(buttonJoinMiter, 0);
-	buttonsJoins->addButton(buttonJoinBevel, 1);
 	buttonsJoins->addButton(buttonJoinRound, 2);
+	buttonsJoins->addButton(buttonJoinBevel, 1);
 
 	lineType->addItem( tr("Custom"));
 
diff --git a/scribus/ui/propertiespalette_line.h b/scribus/ui/propertiespalette_line.h
index d22b310..20350f3 100644
--- a/scribus/ui/propertiespalette_line.h
+++ b/scribus/ui/propertiespalette_line.h
@@ -12,6 +12,7 @@ for which a new license (GPL+exception) is in place.
 #include <QListWidgetItem>
 #include "scribusapi.h"
 #include "scguardedptr.h"
+#include "ui/widgets/buttongroup.h"
 #include "units.h"
 
 class ArrowChooser;
@@ -43,8 +44,8 @@ protected:
 	PageItem *m_item {nullptr};
 	ScribusMainWindow* m_ScMW {nullptr};
 	ScGuardedPtr<ScribusDoc> m_doc;
-	QButtonGroup *buttonsCaps;
-	QButtonGroup *buttonsJoins;
+	ButtonGroup *buttonsCaps;
+	ButtonGroup *buttonsJoins;
 	LineMarkerSelector *lineMarkerSelectorStart;
 	LineMarkerSelector *lineMarkerSelectorEnd;
 
diff --git a/scribus/ui/propertywidget_fontfeatures.cpp b/scribus/ui/propertywidget_fontfeatures.cpp
index 3e2dbd0..093cea3 100644
--- a/scribus/ui/propertywidget_fontfeatures.cpp
+++ b/scribus/ui/propertywidget_fontfeatures.cpp
@@ -16,6 +16,7 @@ for which a new license (GPL+exception) is in place.
 #include "scribusapp.h"
 #include "scribusdoc.h"
 #include "selection.h"
+#include "ui/widgets/buttongroup.h"
 
 #include "fonts/fontfeatures.h"
 
@@ -833,7 +834,7 @@ void PropertyWidget_FontFeatures::initWidgets()
 	OrdinalCheck->installEventFilter(this);
 	SlashedZeroCheck->installEventFilter(this);
 
-	QButtonGroup * groupCapitals = new QButtonGroup();
+	ButtonGroup * groupCapitals = new ButtonGroup();
 	groupCapitals->setExclusive(true);
 	groupCapitals->addButton(NormalCapRadio);
 	groupCapitals->addButton(SmallRadio);
@@ -845,19 +846,26 @@ void PropertyWidget_FontFeatures::initWidgets()
 	groupCapitals->addButton(UnicaseRadio);
 	groupCapitals->addButton(TitlingRadio);
 
-	QButtonGroup * groupFractions = new QButtonGroup();
+	ButtonGroup * groupPosition = new ButtonGroup();
+	groupPosition->setExclusive(true);
+	groupPosition->addButton(DefaultPosRadio);
+	groupPosition->addButton(SubscriptRadio);
+	groupPosition->addButton(SuperscriptRadio);
+	groupPosition->addButton(OrdinalCheck);
+
+	ButtonGroup * groupFractions = new ButtonGroup();
 	groupFractions->setExclusive(true);
 	groupFractions->addButton(DefaultFractionsRadio);
 	groupFractions->addButton(DiagonalRadio);
 	groupFractions->addButton(StackedRadio);
 
-	QButtonGroup * groupNumeralStyle = new QButtonGroup();
+	ButtonGroup * groupNumeralStyle = new ButtonGroup();
 	groupNumeralStyle->setExclusive(true);
 	groupNumeralStyle->addButton(DefaultStyleRadio);
 	groupNumeralStyle->addButton(LiningRadio);
 	groupNumeralStyle->addButton(OldStyleRadio);
 
-	QButtonGroup * groupNumeralWidth = new QButtonGroup();
+	ButtonGroup * groupNumeralWidth = new ButtonGroup();
 	groupNumeralWidth->setExclusive(true);
 	groupNumeralWidth->addButton(DefaultWidthRadio);
 	groupNumeralWidth->addButton(ProportionalRadio);
@@ -870,31 +878,10 @@ void PropertyWidget_FontFeatures::initWidgets()
 	HistoricalCheck->setChecked(false);
 	
 	NormalCapRadio->setChecked(true);
-	// SmallRadio->setChecked(false);
-	// SmallFromCRadio->setChecked(false);
-	// AllSmallCapsRadio->setChecked(false);
-	// PetiteRadio->setChecked(false);
-	// PetiteCapRadio->setChecked(false);
-	// AllPetiteCapsRadio->setChecked(false);
-	// UnicaseRadio->setChecked(false);
-	// TitlingRadio->setChecked(false);
-
 	DefaultStyleRadio->setChecked(true);
-	// LiningRadio->setChecked(false);
-	// OldStyleRadio->setChecked(false);
-
 	DefaultWidthRadio->setChecked(true);
-	// ProportionalRadio->setChecked(false);
-	// TabularRadio->setChecked(false);
-	
 	DefaultFractionsRadio->setChecked(true);
-	// DiagonalRadio->setChecked(false);
-	// StackedRadio->setChecked(false);
-
 	DefaultPosRadio->setChecked(true);
-	// SubscriptRadio->setChecked(false);
-	// SuperscriptRadio->setChecked(false);
-	// OrdinalCheck->setChecked(false);
 
 	SlashedZeroCheck->setChecked(false);
 
diff --git a/scribus/ui/smalignselect.cpp b/scribus/ui/smalignselect.cpp
index 25edea2..35d6064 100644
--- a/scribus/ui/smalignselect.cpp
+++ b/scribus/ui/smalignselect.cpp
@@ -4,24 +4,28 @@ to the COPYING file provided with the program. Following this notice may exist
 a copyright and/or license notice that predates the release of Scribus 1.3.2
 for which a new license (GPL+exception) is in place.
 */
+#include <QLayoutItem>
 #include <QToolTip>
 #include "smalignselect.h"
-#include "iconmanager.h"
-#include "scribusapp.h"
+#include "iconmanager.h"
+#include "scribusapp.h"
 
 SMAlignSelect::SMAlignSelect(QWidget *parent)
 	: AlignSelect(parent)
 {
+	QSpacerItem * spacer = new QSpacerItem(4, 0, QSizePolicy::Fixed);
+	layout()->addItem(spacer);
+
 	parentButton = new QToolButton(this);
-	parentButton->setText( "");
+	parentButton->setText( "");
 	parentButton->setToolTip( tr("Use parent style's alignment instead of overriding it"));
-	addWidget( parentButton );
+	addWidget( parentButton );
 	resize(minimumSizeHint());
 	parentButton->hide();
-
-	iconSetChange();
-
-	connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
+
+	iconSetChange();
+
+	connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
 }
 
 void SMAlignSelect::setStyle(int a, int d)
@@ -79,9 +83,9 @@ void SMAlignSelect::pbPressed()
 {
 	m_useParentStyle = true;
 }
-
-void SMAlignSelect::iconSetChange()
-{
-	IconManager &im = IconManager::instance();
-	parentButton->setIcon(im.loadIcon("reset-style-changes"));
-}
+
+void SMAlignSelect::iconSetChange()
+{
+	IconManager &im = IconManager::instance();
+	parentButton->setIcon(im.loadIcon("reset-style-changes"));
+}
diff --git a/scribus/ui/styleselect.cpp b/scribus/ui/styleselect.cpp
index ab7c677..a1d6920 100644
--- a/scribus/ui/styleselect.cpp
+++ b/scribus/ui/styleselect.cpp
@@ -10,6 +10,7 @@ for which a new license (GPL+exception) is in place.
 #include "iconmanager.h"
 #include "scribusapp.h"
 #include "styleselect.h"
+#include "ui/widgets/buttongroup.h"
 
 StrikeValues::StrikeValues( QWidget* parent ) : QFrame( parent )
 {
@@ -130,7 +131,7 @@ void ShadowValues::languageChange()
 StyleSelect::StyleSelect(QWidget* parent) : QWidget(parent)
 {
 	ssLayout = new QHBoxLayout(this);
-	ssLayout->setSpacing(4);
+	ssLayout->setSpacing(0);
 	ssLayout->setContentsMargins(0, 0, 0, 0);
 
 	UnderlineVal = new UnderlineValues( nullptr );
@@ -144,12 +145,18 @@ StyleSelect::StyleSelect(QWidget* parent) : QWidget(parent)
 	underlineButton->setMenu(UnderlinePop);
 	underlineButton->setPopupMode(QToolButton::DelayedPopup);
 	ssLayout->addWidget( underlineButton );
+
+	ssLayout->addSpacing(4);
+
 	underlineWordButton = new QToolButton( this );
 	underlineWordButton->setText( "" );
 	underlineWordButton->setCheckable( true );
 	underlineWordButton->setMenu(UnderlinePop);
 	underlineWordButton->setPopupMode(QToolButton::DelayedPopup);
-	ssLayout->addWidget( underlineWordButton );	
+	ssLayout->addWidget( underlineWordButton );
+
+	ssLayout->addSpacing(4);
+
 	StrikeVal = new StrikeValues( nullptr );
 	StrikePop = new QMenu();
 	StrikeValAct = new QWidgetAction(this);
@@ -162,7 +169,7 @@ StyleSelect::StyleSelect(QWidget* parent) : QWidget(parent)
 	strikeoutButton->setPopupMode(QToolButton::DelayedPopup);
 	ssLayout->addWidget( strikeoutButton );
 
-	ssLayout->addSpacing(12);
+	ssLayout->addSpacing(16);
 
 	subscriptButton = new QToolButton( this );
 	subscriptButton->setText( "" );
@@ -173,7 +180,12 @@ StyleSelect::StyleSelect(QWidget* parent) : QWidget(parent)
 	superscriptButton->setCheckable( true );
 	ssLayout->addWidget( superscriptButton );
 
-	ssLayout->addSpacing(12);
+	ButtonGroup *bgSub = new ButtonGroup();
+	bgSub->setExclusive(false);
+	bgSub->addButton(subscriptButton);
+	bgSub->addButton(superscriptButton);
+
+	ssLayout->addSpacing(16);
 
 	allcapsButton = new QToolButton( this );
 	allcapsButton->setText("");
@@ -184,7 +196,12 @@ StyleSelect::StyleSelect(QWidget* parent) : QWidget(parent)
 	smallcapsButton->setCheckable( true );
 	ssLayout->addWidget( smallcapsButton );
 
-	ssLayout->addSpacing(12);
+	ButtonGroup *bgCaps = new ButtonGroup();
+	bgCaps->setExclusive(false);
+	bgCaps->addButton(allcapsButton);
+	bgCaps->addButton(smallcapsButton);
+
+	ssLayout->addSpacing(16);
 
 	OutlineVal = new OutlineValues( nullptr );
 	OutlinePop = new QMenu();
@@ -198,6 +215,8 @@ StyleSelect::StyleSelect(QWidget* parent) : QWidget(parent)
 	outlineButton->setPopupMode(QToolButton::DelayedPopup);
 	ssLayout->addWidget( outlineButton );
 
+	ssLayout->addSpacing(4);
+
 	ShadowVal = new ShadowValues( nullptr );
 	ShadowPop = new QMenu();
 	ShadowValAct = new QWidgetAction(this);
buttongroup_2025-07-04_01.patch (19,671 bytes)   
files.zip (13,836 bytes)
preview.png (9,894 bytes)   
preview.png (9,894 bytes)   
PatchYes

Relationships

related to 0017391 closednitramr Add Dark/Light theme switch to override automatic mode 

Activities

jghali

2025-07-06 17:08

administrator   ~0052878

There is a memory leak issue in ButtonGroup::updateStyle() : ToolButtonStyle objects are created with new and setup with QWidget setStyle(), but Qt doc states : "The ownership of the style object is not transferred". So each time ButtonGroup::updateStyle() will be called, ToolButtonStyle objects created by the previous ButtonGroup::updateStyle() call will be leaked.

jghali

2025-07-06 17:17

administrator   ~0052879

Also it appears ButtonGroup fails to support dark theme properly on Windows.
17571_buttongroup_windows.png (12,679 bytes)   
17571_buttongroup_windows.png (12,679 bytes)   

nitramr

2025-10-22 21:55

developer   ~0053100

I've updated the patch.

There are three classes:
- ButtonGroup
- ToolButton
- ScribusProxyStyle

The ToolButton is a QToolButton with additional properties for shape information to allow it to be used within a ButtonGroup.

The ButtonGroup extends the QButtonGroup to restyle the ToolButtons when their visibility changes.

The ScribusProxyStyle is a new style class to apply the new shapes to the ToolButton. This class can be extended later to ensure a consistent style for all widgets across all operating systems.

The ScribusProxyStyle installs an event listener for the ScQApp class to listen for QThemeChanges events. This event is triggered when the operating system's dark/light theme changes. @cbradney, this fixes the MDI window title bar issues on Mac.

The patch was tested on Ubuntu 25.04 and macOS 16, not on Windows.
buttongroup_2025-10-22_01.patch (27,204 bytes)   
Index: scribus/CMakeLists_Sources.txt
===================================================================
--- scribus/CMakeLists_Sources.txt	(Revision 27090)
+++ scribus/CMakeLists_Sources.txt	(Arbeitskopie)
@@ -565,4 +565,6 @@
 	ui/delegates/sclistitemdelegate.cpp
 	ui/docks/dock_centralwidget.cpp
 	ui/docks/dock_panelbase.cpp
+	ui/factories/scribusproxystyle.cpp
+	ui/widgets/buttongroup.cpp
 	ui/widgets/color_button.cpp
Index: scribus/scribus.cpp
===================================================================
--- scribus/scribus.cpp	(Revision 27090)
+++ scribus/scribus.cpp	(Arbeitskopie)
@@ -239,6 +239,7 @@
 #include "ui/tabmanager.h"
 #include "ui/transformdialog.h"
 #include "ui/viewtoolbar.h"
+#include "ui/factories/scribusproxystyle.h"
 #include "undogui.h"
 #include "undomanager.h"
 #include "undostate.h"
@@ -6480,7 +6481,6 @@
 	LocaleManager::instance().setUserPreferredLocale(m_prefsManager.appPrefs.uiPrefs.userPreferredLocale);
 	ScQApp->setLocale();
 
-	bool forceStyleUpdate = false;
 	bool useDefaultScratchColor = false;
 	if (m_prefsManager.appPrefs.displayPrefs.scratchColor == QApplication::palette().color(QPalette::Active, QPalette::Window))
 		useDefaultScratchColor = true;
@@ -6489,37 +6489,19 @@
 	QString newUIStylePalette = m_prefsManager.appPrefs.uiPrefs.stylePalette;
 	if (oldPrefs.uiPrefs.stylePalette != newUIStylePalette)
 	{
-		forceStyleUpdate = true;
 
 		if (newUIStylePalette == "dark")
-		{
-			QApplication::styleHints()->setColorScheme(Qt::ColorScheme::Dark);
-#if (defined Q_OS_LINUX)
-			QPalette pal(QColor(49, 49, 49));
-			QApplication::setPalette(pal);
-#endif
-		}
+			ScribusProxyStyle::instance()->setApplicationTheme(ScribusProxyStyle::ApplicationTheme::Dark);
 		else if (newUIStylePalette == "light")
-		{
-			QApplication::styleHints()->setColorScheme(Qt::ColorScheme::Light);
-#if (defined Q_OS_LINUX)
-			QPalette pal(QColor(239, 239, 239));
-			QApplication::setPalette(pal);
-#endif
-		}
+			ScribusProxyStyle::instance()->setApplicationTheme(ScribusProxyStyle::ApplicationTheme::Light);
 		else
-		{
-			QApplication::styleHints()->unsetColorScheme();
-#if (defined Q_OS_LINUX)
-			QApplication::setPalette(this->style()->standardPalette());
-#endif
-		}
+			ScribusProxyStyle::instance()->setApplicationTheme(ScribusProxyStyle::ApplicationTheme::System);
 	}
 #endif
 
 	bool forceIconUpdate = false;
 	QString newUIStyle = m_prefsManager.guiStyle();
-	if (oldPrefs.uiPrefs.style != newUIStyle || forceStyleUpdate == true)
+	if (oldPrefs.uiPrefs.style != newUIStyle)
 	{
 		forceIconUpdate = true;
 
@@ -6527,11 +6509,11 @@
 		if (!newUIStyle.isEmpty())
 			styleName = newUIStyle;
 
-		QStyle * newStyle = QStyleFactory::create(styleName);
-		if (newStyle)
-			QApplication::setStyle(newStyle);
-		else
-			m_prefsManager.appPrefs.uiPrefs.style = oldPrefs.uiPrefs.style;
+		ScribusProxyStyle::instance()->setBaseStyleName(styleName);
+		// if (scStyle)
+		// 	ScQApp->setStyle(scStyle);
+		// else
+		// 	m_prefsManager.appPrefs.uiPrefs.style = oldPrefs.uiPrefs.style;
 	}
 
 	if (useDefaultScratchColor)
Index: scribus/scribusapp.cpp
===================================================================
--- scribus/scribusapp.cpp	(Revision 27090)
+++ scribus/scribusapp.cpp	(Arbeitskopie)
@@ -707,7 +707,16 @@
 			}
 			return true;
 		}
+	case QEvent::ApplicationPaletteChange:
+		{
+			IconManager &im = IconManager::instance();
+			im.rebuildCache();
+			emit iconSetChanged();
+		}
+		break;
 	default:
-		return QApplication::event(event);
+			break;
 	}
+
+	return QApplication::event(event);
 }
Index: scribus/scribuscore.cpp
===================================================================
--- scribus/scribuscore.cpp	(Revision 27090)
+++ scribus/scribuscore.cpp	(Arbeitskopie)
@@ -45,6 +45,7 @@
 #include "scribus.h"
 #include "scribusapp.h"
 #include "ui/splash.h"
+#include "ui/factories/scribusproxystyle.h"
 #include "undomanager.h"
 #include "util_debug.h"
 #include "util_ghostscript.h"
@@ -179,45 +180,41 @@
 	// This is a very basic implemenation of the UI theme palette.
 	// If necessary implement platform specific theme configurations here.
 
+
+	// Configure GUI
+	const QString& prefsUiStyle = m_prefsManager.appPrefs.uiPrefs.style;
+	QString qtStyle = nullptr;
+	if (prefsUiStyle.length() > 0)
+	{
+		QStringList availableStyles = QStyleFactory::keys();
+		if (availableStyles.contains(prefsUiStyle))
+			qtStyle = prefsUiStyle;
+		else
+			m_prefsManager.appPrefs.uiPrefs.style.clear();
+	}
+
+	ScribusProxyStyle* scStyle = new ScribusProxyStyle(qtStyle);
+	scStyle->setParent(qApp);
+
 	// Apply different palette only if the system UI palette is different.
 #if (QT_VERSION >= QT_VERSION_CHECK(6, 8, 0))
 	if (m_prefsManager.appPrefs.uiPrefs.stylePalette == "dark" && QApplication::styleHints()->colorScheme() == Qt::ColorScheme::Light)
 	{
-		QApplication::styleHints()->setColorScheme(Qt::ColorScheme::Dark);
-
-	// https://bugreports.qt.io/browse/QTBUG-132929
-#if (defined Q_OS_LINUX)
-		QPalette pal(QColor(49, 49, 49));
-		QApplication::setPalette(pal);
-#endif
+		scStyle->setApplicationTheme(ScribusProxyStyle::ApplicationTheme::Dark);
 		m_SplashScreen->setPixmap(m_iconManager.splashScreen());
 	}
 	else if (m_prefsManager.appPrefs.uiPrefs.stylePalette == "light" && QApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark)
 	{
-		QApplication::styleHints()->setColorScheme(Qt::ColorScheme::Light);
-
-	// https://bugreports.qt.io/browse/QTBUG-132929
-#if (defined Q_OS_LINUX)
-		QPalette pal(QColor(239, 239, 239));
-		QApplication::setPalette(pal);
-#endif
+		scStyle->setApplicationTheme(ScribusProxyStyle::ApplicationTheme::Light);
 		m_SplashScreen->setPixmap(m_iconManager.splashScreen());
 	}
+	else
+		scStyle->setApplicationTheme(ScribusProxyStyle::ApplicationTheme::System);
 #endif
 
-	// Configure GUI
-	const QString& prefsUiStyle = m_prefsManager.appPrefs.uiPrefs.style;
-	if (prefsUiStyle.length() > 0)
-	{
-		QStyle* qtStyle = nullptr;
-		QStringList availableStyles = QStyleFactory::keys();
-		if (availableStyles.contains(prefsUiStyle))
-			qtStyle = QStyleFactory::create(prefsUiStyle);
-		if (qtStyle)
-			QApplication::setStyle(qtStyle);
-		else
-			m_prefsManager.appPrefs.uiPrefs.style.clear();
-	}
+	qApp->setStyle(scStyle);
+	qApp->installEventFilter(scStyle);
+
 	QFont apf = QApplication::font();
 	apf.setPointSize(m_prefsManager.appPrefs.uiPrefs.applicationFontSize);
 	QApplication::setFont(apf);
Index: scribus/ui/alignselect.cpp
===================================================================
--- scribus/ui/alignselect.cpp	(Revision 27090)
+++ scribus/ui/alignselect.cpp	(Arbeitskopie)
@@ -16,26 +16,26 @@
 
 AlignSelect::AlignSelect(QWidget* parent) : FormWidget(parent)
 {
-	buttonGroup = new QButtonGroup(this);
+	buttonGroup = new ButtonGroup(this);
 
-	TextL = new QToolButton( this );
+	TextL = new ToolButton( this );
 	TextL->setCheckable( true );
 	TextL->setChecked( true );
 	buttonGroup->addButton(TextL, 0);
 
-	TextC = new QToolButton( this );
+	TextC = new ToolButton( this );
 	TextC->setCheckable( true );
 	buttonGroup->addButton(TextC, 1);
 
-	TextR = new QToolButton( this );
+	TextR = new ToolButton( this );
 	TextR->setCheckable( true );
 	buttonGroup->addButton(TextR, 2);
 
-	TextB = new QToolButton( this );
+	TextB = new ToolButton( this );
 	TextB->setCheckable( true );
 	buttonGroup->addButton(TextB, 3);
 
-	TextF = new QToolButton( this );
+	TextF = new ToolButton( this );
 	TextF->setCheckable( true );
 	buttonGroup->addButton(TextF, 4);
 
@@ -45,6 +45,9 @@
 	addWidget(TextB);
 	addWidget(TextF);
 
+	// Modifiy layout spacing. Layout is created by addWidget()
+	layout()->setSpacing(0);
+
 	iconSetChange();
 	languageChange();
 
Index: scribus/ui/alignselect.h
===================================================================
--- scribus/ui/alignselect.h	(Revision 27090)
+++ scribus/ui/alignselect.h	(Arbeitskopie)
@@ -14,6 +14,7 @@
 class QEvent;
 
 #include "scribusapi.h"
+#include "ui/widgets/buttongroup.h"
 #include "ui/widgets/form_widget.h"
 
 class SCRIBUS_API AlignSelect : public FormWidget
@@ -30,12 +31,12 @@
 	int selectedId() const;
 
 	int selected { 0 };
-	QButtonGroup* buttonGroup { nullptr };
-	QToolButton* TextL { nullptr };
-	QToolButton* TextR { nullptr };
-	QToolButton* TextC { nullptr };
-	QToolButton* TextB { nullptr };
-	QToolButton* TextF { nullptr };
+	ButtonGroup* buttonGroup { nullptr };
+	ToolButton* TextL { nullptr };
+	ToolButton* TextR { nullptr };
+	ToolButton* TextC { nullptr };
+	ToolButton* TextB { nullptr };
+	ToolButton* TextF { nullptr };
 
 public slots:
 	void iconSetChange();
Index: scribus/ui/alignverticalselect.cpp
===================================================================
--- scribus/ui/alignverticalselect.cpp	(Revision 27090)
+++ scribus/ui/alignverticalselect.cpp	(Arbeitskopie)
@@ -16,19 +16,19 @@
 
 AlignVerticalSelect::AlignVerticalSelect(QWidget* parent) : FormWidget(parent)
 {
-	buttonGroup = new QButtonGroup(this);
+	buttonGroup = new ButtonGroup(this);
 	buttonGroup->setExclusive(true);
 
-	TextT = new QToolButton( this );
+	TextT = new ToolButton( this );
 	TextT->setCheckable( true );
 	TextT->setChecked( true );
 	buttonGroup->addButton(TextT, 0);
 
-	TextC = new QToolButton( this );
+	TextC = new ToolButton( this );
 	TextC->setCheckable( true );
 	buttonGroup->addButton(TextC, 1);
 
-	TextB = new QToolButton( this );
+	TextB = new ToolButton( this );
 	TextB->setCheckable( true );
 	buttonGroup->addButton(TextB, 2);
 
@@ -36,6 +36,9 @@
 	addWidget(TextC);
 	addWidget(TextB);
 
+	// Modifiy layout spacing. Layout is created by addWidget()
+	layout()->setSpacing(0);
+
 	iconSetChange();
 	languageChange();
 
Index: scribus/ui/alignverticalselect.h
===================================================================
--- scribus/ui/alignverticalselect.h	(Revision 27090)
+++ scribus/ui/alignverticalselect.h	(Arbeitskopie)
@@ -14,6 +14,7 @@
 class QEvent;
 
 #include "scribusapi.h"
+#include "ui/widgets/buttongroup.h"
 #include "ui/widgets/form_widget.h"
 
 class SCRIBUS_API AlignVerticalSelect : public FormWidget
@@ -28,10 +29,10 @@
 	void setStyle(int s);
 	int getStyle() const;
 
-	QButtonGroup* buttonGroup { nullptr };
-	QToolButton* TextT { nullptr };
-	QToolButton* TextC { nullptr };
-	QToolButton* TextB { nullptr };
+	ButtonGroup* buttonGroup { nullptr };
+	ToolButton* TextT { nullptr };
+	ToolButton* TextC { nullptr };
+	ToolButton* TextB { nullptr };
 
 public slots:
 	void iconSetChange();
Index: scribus/ui/directionselect.cpp
===================================================================
--- scribus/ui/directionselect.cpp	(Revision 27090)
+++ scribus/ui/directionselect.cpp	(Arbeitskopie)
@@ -15,24 +15,32 @@
 
 DirectionSelect::DirectionSelect(QWidget* parent) : FormWidget(parent)
 {
-	buttonGroup = new QButtonGroup(this);
+	buttonGroup = new ButtonGroup(this);
 
-	LTR = new QToolButton( this );
+	QHBoxLayout* lay = new QHBoxLayout();
+	lay->setContentsMargins(0, 0, 0, 0);
+	lay->setSpacing(0);
+	lay->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
+	setLayout(lay);
+
+	LTR = new ToolButton( this );
 	LTR->setCheckable( true );
 	LTR->setChecked( true );
 	addWidget( LTR );
 	buttonGroup->addButton(LTR, 0);
 
-	RTL = new QToolButton( this );
+	RTL = new ToolButton( this );
 	RTL->setCheckable( true );
 	addWidget( RTL );
 	buttonGroup->addButton(RTL, 1);
 
-	resize(minimumSizeHint());
+	lay->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
 
 	iconSetChange();
 	languageChange();
 
+	resize(minimumSizeHint());
+
 	connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
 	connect(buttonGroup, SIGNAL(idClicked(int)), this, SLOT(setTypeStyle(int)));
 }
Index: scribus/ui/directionselect.h
===================================================================
--- scribus/ui/directionselect.h	(Revision 27090)
+++ scribus/ui/directionselect.h	(Arbeitskopie)
@@ -16,6 +16,7 @@
 class QEvent;
 
 #include "scribusapi.h"
+#include "ui/widgets/buttongroup.h"
 #include "ui/widgets/form_widget.h"
 
 class SCRIBUS_API DirectionSelect : public FormWidget
@@ -30,9 +31,9 @@
 		int getStyle();
 		int selectedId();
 
-		QButtonGroup* buttonGroup { nullptr };
-		QToolButton* RTL { nullptr };
-		QToolButton* LTR { nullptr };
+		ButtonGroup* buttonGroup { nullptr };
+		ToolButton* RTL { nullptr };
+		ToolButton* LTR { nullptr };
 
 	public slots:
 		void iconSetChange();
Index: scribus/ui/flopwidget.cpp
===================================================================
--- scribus/ui/flopwidget.cpp	(Revision 27090)
+++ scribus/ui/flopwidget.cpp	(Arbeitskopie)
@@ -11,22 +11,22 @@
 #include "scribusapp.h"
 
 FlopWidget::FlopWidget(QWidget* parent) : FormWidget(parent)
-{	
+{
 
-	flopRealHeight = new QToolButton();
+	flopRealHeight = new ToolButton();
 	flopRealHeight->setCheckable(true);
 	flopRealHeight->setChecked(true);	
-	flopFontAscent = new QToolButton();
+	flopFontAscent = new ToolButton();
 	flopFontAscent->setCheckable(true);
-	flopLineSpacing = new QToolButton();
+	flopLineSpacing = new ToolButton();
 	flopLineSpacing->setCheckable(true);
-	flopBaselineGrid = new QToolButton();
+	flopBaselineGrid = new ToolButton();
 	flopBaselineGrid->setCheckable(true);
 
-	flopGroup = new QButtonGroup();
+	flopGroup = new ButtonGroup();
 	flopGroup->setExclusive(true);
+	flopGroup->addButton(flopFontAscent,  FontAscentID);
 	flopGroup->addButton(flopRealHeight,  RealHeightID);
-	flopGroup->addButton(flopFontAscent,  FontAscentID);
 	flopGroup->addButton(flopLineSpacing, LineSpacingID);
 	flopGroup->addButton(flopBaselineGrid, BaselineGridID);
 
@@ -35,6 +35,9 @@
 	addWidget(flopLineSpacing);
 	addWidget(flopBaselineGrid);
 
+	// Modifiy layout spacing. Layout is created by addWidget()
+	layout()->setSpacing(0);
+
 	iconSetChange();
 	languageChange();
 
Index: scribus/ui/flopwidget.h
===================================================================
--- scribus/ui/flopwidget.h	(Revision 27090)
+++ scribus/ui/flopwidget.h	(Arbeitskopie)
@@ -9,7 +9,9 @@
 
 
 #include <QButtonGroup>
+#include <QHBoxLayout>
 #include <QToolButton>
+#include "ui/widgets/buttongroup.h"
 #include "ui/widgets/form_widget.h"
 
 class ScribusDoc;
@@ -31,11 +33,11 @@
 	FlopWidget(QWidget* parent);
 	~FlopWidget() {};
 
-	QButtonGroup *flopGroup;
-	QToolButton *flopRealHeight = {nullptr};
-	QToolButton *flopFontAscent = {nullptr};
-	QToolButton *flopLineSpacing = {nullptr};
-	QToolButton *flopBaselineGrid = {nullptr};
+	ButtonGroup *flopGroup;
+	ToolButton *flopRealHeight = {nullptr};
+	ToolButton *flopFontAscent = {nullptr};
+	ToolButton *flopLineSpacing = {nullptr};
+	ToolButton *flopBaselineGrid = {nullptr};
 
 protected:
Index: scribus/ui/newdocdialog.cpp
===================================================================
--- scribus/ui/newdocdialog.cpp	(Revision 27090)
+++ scribus/ui/newdocdialog.cpp	(Arbeitskopie)
@@ -143,12 +142,12 @@
 	comboSortSizes->addItem( tr("Size Desc"), PageSizeList::DimensionDesc);
 	comboSortSizes->setCurrentIndex(0);
 
-	pageOrientationButtons = new QButtonGroup();
+	pageOrientationButtons = new ButtonGroup();
 	pageOrientationButtons->addButton(buttonVertical, 0);
 	pageOrientationButtons->addButton(buttonHorizontal, 1);
 	pageOrientationButtons->button(orientation)->setChecked(true);
 
-	pageLayoutButtons = new QButtonGroup();
+	pageLayoutButtons = new ButtonGroup();
 	pageLayoutButtons->addButton(buttonSinglePage, 0);
 	pageLayoutButtons->addButton(buttonDoublePageLeft, 1);
 	pageLayoutButtons->addButton(buttonDoublePageRight, 2); 
Index: scribus/ui/newdocdialog.h
===================================================================
--- scribus/ui/newdocdialog.h	(Revision 27090)
+++ scribus/ui/newdocdialog.h	(Arbeitskopie)
@@ -34,6 +34,7 @@
 #include "scribusstructs.h"
 #include "ui/customfdialog.h"
 #include "ui/nftwidget.h"
+#include "ui/widgets/buttongroup.h"
 
 #include "ui_newdocdialog.h"
 
@@ -120,8 +120,8 @@
 protected:
 	PrefsManager& prefsManager;
 	QStringList recentDocList;
-	QButtonGroup* pageOrientationButtons;
-	QButtonGroup* pageLayoutButtons;
+	ButtonGroup* pageOrientationButtons;
+	ButtonGroup* pageLayoutButtons;
 
 	double m_unitRatio { 1.0 };
 	int m_orientation { 0 };
Index: scribus/ui/propertiespalette_fill.cpp
===================================================================
--- scribus/ui/propertiespalette_fill.cpp	(Revision 27090)
+++ scribus/ui/propertiespalette_fill.cpp	(Arbeitskopie)
@@ -8,6 +8,7 @@
 #include "selection.h"
 #include "undomanager.h"
 #include "ui/colorpicker/colorpicker.h"
+#include "ui/widgets/buttongroup.h"
 
 PropertiesPalette_Fill::PropertiesPalette_Fill(QWidget *parent) :
 	QWidget(parent)
@@ -23,6 +24,10 @@
 
 	undoManager = UndoManager::instance();
 
+	ButtonGroup * fillRuleGroup = new ButtonGroup();
+	fillRuleGroup->addButton(evenOdd);
+	fillRuleGroup->addButton(nonZero);
+
 	iconSetChange();
 	languageChange();
 
Index: scribus/ui/propertiespalette_line.cpp
===================================================================
--- scribus/ui/propertiespalette_line.cpp	(Revision 27090)
+++ scribus/ui/propertiespalette_line.cpp	(Arbeitskopie)
@@ -39,15 +39,15 @@
 	setupUi(this);
 	setSizePolicy( QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum));
 
-	buttonsCaps = new QButtonGroup();
+	buttonsCaps = new ButtonGroup();
 	buttonsCaps->addButton(buttonCapFlat, 0);
 	buttonsCaps->addButton(buttonCapSquare, 1);
 	buttonsCaps->addButton(buttonCapRound, 2);
 
-	buttonsJoins = new QButtonGroup();
+	buttonsJoins = new ButtonGroup();
 	buttonsJoins->addButton(buttonJoinMiter, 0);
+	buttonsJoins->addButton(buttonJoinRound, 2);
 	buttonsJoins->addButton(buttonJoinBevel, 1);
-	buttonsJoins->addButton(buttonJoinRound, 2);
 
 	lineType->addItem( tr("Custom"));
 
Index: scribus/ui/propertiespalette_line.h
===================================================================
--- scribus/ui/propertiespalette_line.h	(Revision 27090)
+++ scribus/ui/propertiespalette_line.h	(Arbeitskopie)
@@ -12,6 +12,7 @@
 #include <QListWidgetItem>
 #include "scribusapi.h"
 #include "scguardedptr.h"
+#include "ui/widgets/buttongroup.h"
 #include "units.h"
 
 class ArrowChooser;
@@ -43,8 +44,8 @@
 	PageItem *m_item {nullptr};
 	ScribusMainWindow* m_ScMW {nullptr};
 	ScGuardedPtr<ScribusDoc> m_doc;
-	QButtonGroup *buttonsCaps;
-	QButtonGroup *buttonsJoins;
+	ButtonGroup *buttonsCaps;
+	ButtonGroup *buttonsJoins;
 	LineMarkerSelector *lineMarkerSelectorStart;
 	LineMarkerSelector *lineMarkerSelectorEnd;
 
Index: scribus/ui/propertiespalette_shape.cpp
===================================================================
--- scribus/ui/propertiespalette_shape.cpp	(Revision 27090)
+++ scribus/ui/propertiespalette_shape.cpp	(Arbeitskopie)
@@ -25,6 +25,7 @@
 #include "scribusview.h"
 #include "selection.h"
 #include "units.h"
+#include "ui/widgets/buttongroup.h"
 
 PropertiesPalette_Shape::PropertiesPalette_Shape( QWidget* parent)
 	: QWidget(parent)
@@ -38,6 +39,13 @@
 	iconSetChange();
 	languageChange();
 
+	ButtonGroup * bgFlow = new ButtonGroup();
+	bgFlow->addButton(textFlowDisabled);
+	bgFlow->addButton(textFlowUsesBoundingBox);
+	bgFlow->addButton(textFlowUsesContourLine);
+	bgFlow->addButton(textFlowUsesFrameShape);
+	bgFlow->addButton(textFlowUsesImageClipping);
+
 	connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
 	connect(ScQApp, SIGNAL(localeChanged()), this, SLOT(localeChange()));
 	connect(ScQApp, SIGNAL(labelVisibilityChanged(bool)), this, SLOT(toggleLabelVisibility(bool)));
Index: scribus/ui/propertywidget_fontfeatures.cpp
===================================================================
--- scribus/ui/propertywidget_fontfeatures.cpp	(Revision 27090)
+++ scribus/ui/propertywidget_fontfeatures.cpp	(Arbeitskopie)
@@ -16,6 +16,7 @@
 #include "scribusapp.h"
 #include "scribusdoc.h"
 #include "selection.h"
+#include "ui/widgets/buttongroup.h"
 
 #include "fonts/fontfeatures.h"
 
@@ -833,7 +834,7 @@
 	OrdinalCheck->installEventFilter(this);
 	SlashedZeroCheck->installEventFilter(this);
 
-	QButtonGroup * groupCapitals = new QButtonGroup();
+	ButtonGroup * groupCapitals = new ButtonGroup();
 	groupCapitals->setExclusive(true);
 	groupCapitals->addButton(NormalCapRadio);
 	groupCapitals->addButton(SmallRadio);
@@ -845,19 +846,26 @@
 	groupCapitals->addButton(UnicaseRadio);
 	groupCapitals->addButton(TitlingRadio);
 
-	QButtonGroup * groupFractions = new QButtonGroup();
+	ButtonGroup * groupPosition = new ButtonGroup();
+	groupPosition->setExclusive(true);
+	groupPosition->addButton(DefaultPosRadio);
+	groupPosition->addButton(SubscriptRadio);
+	groupPosition->addButton(SuperscriptRadio);
+	groupPosition->addButton(OrdinalCheck);
+
+	ButtonGroup * groupFractions = new ButtonGroup();
 	groupFractions->setExclusive(true);
 	groupFractions->addButton(DefaultFractionsRadio);
 	groupFractions->addButton(DiagonalRadio);
 	groupFractions->addButton(StackedRadio);
 
-	QButtonGroup * groupNumeralStyle = new QButtonGroup();
+	ButtonGroup * groupNumeralStyle = new ButtonGroup();
 	groupNumeralStyle->setExclusive(true);
 	groupNumeralStyle->addButton(DefaultStyleRadio);
 	groupNumeralStyle->addButton(LiningRadio);
 	groupNumeralStyle->addButton(OldStyleRadio);
 
-	QButtonGroup * groupNumeralWidth = new QButtonGroup();
+	ButtonGroup * groupNumeralWidth = new ButtonGroup();
 	groupNumeralWidth->setExclusive(true);
 	groupNumeralWidth->addButton(DefaultWidthRadio);
 	groupNumeralWidth->addButton(ProportionalRadio);
@@ -870,31 +878,10 @@
 	HistoricalCheck->setChecked(false);
 	
 	NormalCapRadio->setChecked(true);
-	// SmallRadio->setChecked(false);
-	// SmallFromCRadio->setChecked(false);
-	// AllSmallCapsRadio->setChecked(false);
-	// PetiteRadio->setChecked(false);
-	// PetiteCapRadio->setChecked(false);
-	// AllPetiteCapsRadio->setChecked(false);
-	// UnicaseRadio->setChecked(false);
-	// TitlingRadio->setChecked(false);
-
 	DefaultStyleRadio->setChecked(true);
-	// LiningRadio->setChecked(false);
-	// OldStyleRadio->setChecked(false);
-
 	DefaultWidthRadio->setChecked(true);
-	// ProportionalRadio->setChecked(false);
-	// TabularRadio->setChecked(false);
-	
 	DefaultFractionsRadio->setChecked(true);
-	// DiagonalRadio->setChecked(false);
-	// StackedRadio->setChecked(false);
-
 	DefaultPosRadio->setChecked(true);
-	// SubscriptRadio->setChecked(false);
-	// SuperscriptRadio->setChecked(false);
-	// OrdinalCheck->setChecked(false);
 
 	SlashedZeroCheck->setChecked(false);
 
Index: scribus/ui/smalignselect.cpp
===================================================================
--- scribus/ui/smalignselect.cpp	(Revision 27090)
+++ scribus/ui/smalignselect.cpp	(Arbeitskopie)
@@ -4,6 +4,7 @@
 a copyright and/or license notice that predates the release of Scribus 1.3.2
 for which a new license (GPL+exception) is in place.
 */
+#include <QLayoutItem>
 #include <QToolTip>
 #include "smalignselect.h"
 #include "iconmanager.h"
@@ -12,6 +13,9 @@
 SMAlignSelect::SMAlignSelect(QWidget *parent)
 	: AlignSelect(parent)
 {
+	QSpacerItem * spacer = new QSpacerItem(4, 0, QSizePolicy::Fixed);
+	layout()->addItem(spacer);
+
 	parentButton = new QToolButton(this);
 	parentButton->setText( "");
 	parentButton->setToolTip( tr("Use parent style's alignment instead of overriding it"));
Index: scribus/ui/styleselect.cpp
===================================================================
--- scribus/ui/styleselect.cpp	(Revision 27090)
+++ scribus/ui/styleselect.cpp	(Arbeitskopie)
@@ -130,7 +130,7 @@
 StyleSelect::StyleSelect(QWidget* parent) : QWidget(parent)
 {
 	ssLayout = new QHBoxLayout(this);
-	ssLayout->setSpacing(4);
+	ssLayout->setSpacing(0);
 	ssLayout->setContentsMargins(0, 0, 0, 0);
 
 	UnderlineVal = new UnderlineValues( nullptr );
@@ -144,12 +144,18 @@
 	underlineButton->setMenu(UnderlinePop);
 	underlineButton->setPopupMode(QToolButton::DelayedPopup);
 	ssLayout->addWidget( underlineButton );
+
+	ssLayout->addSpacing(4);
+
 	underlineWordButton = new QToolButton( this );
 	underlineWordButton->setText( "" );
 	underlineWordButton->setCheckable( true );
 	underlineWordButton->setMenu(UnderlinePop);
 	underlineWordButton->setPopupMode(QToolButton::DelayedPopup);
-	ssLayout->addWidget( underlineWordButton );	
+	ssLayout->addWidget( underlineWordButton );
+
+	ssLayout->addSpacing(4);
+
 	StrikeVal = new StrikeValues( nullptr );
 	StrikePop = new QMenu();
 	StrikeValAct = new QWidgetAction(this);
@@ -162,30 +168,40 @@
 	strikeoutButton->setPopupMode(QToolButton::DelayedPopup);
 	ssLayout->addWidget( strikeoutButton );
 
-	ssLayout->addSpacing(12);
+	ssLayout->addSpacing(16);
 
-	subscriptButton = new QToolButton( this );
+	subscriptButton = new ToolButton( this );
 	subscriptButton->setText( "" );
 	subscriptButton->setCheckable( true );
 	ssLayout->addWidget( subscriptButton );
-	superscriptButton = new QToolButton( this );
+	superscriptButton = new ToolButton( this );
 	superscriptButton->setText( "" );
 	superscriptButton->setCheckable( true );
 	ssLayout->addWidget( superscriptButton );
 
-	ssLayout->addSpacing(12);
+	ButtonGroup *bgSub = new ButtonGroup();
+	bgSub->setExclusive(false);
+	bgSub->addButton(subscriptButton);
+	bgSub->addButton(superscriptButton);
 
-	allcapsButton = new QToolButton( this );
+	ssLayout->addSpacing(16);
+
+	allcapsButton = new ToolButton( this );
 	allcapsButton->setText("");
 	allcapsButton->setCheckable( true );
 	ssLayout->addWidget( allcapsButton );
-	smallcapsButton = new QToolButton( this );
+	smallcapsButton = new ToolButton( this );
 	smallcapsButton->setText("");
 	smallcapsButton->setCheckable( true );
 	ssLayout->addWidget( smallcapsButton );
 
-	ssLayout->addSpacing(12);
+	ButtonGroup *bgCaps = new ButtonGroup();
+	bgCaps->setExclusive(false);
+	bgCaps->addButton(allcapsButton);
+	bgCaps->addButton(smallcapsButton);
 
+	ssLayout->addSpacing(16);
+
 	OutlineVal = new OutlineValues( nullptr );
 	OutlinePop = new QMenu();
 	OutlineValAct = new QWidgetAction(this);
@@ -198,6 +214,8 @@
 	outlineButton->setPopupMode(QToolButton::DelayedPopup);
 	ssLayout->addWidget( outlineButton );
 
+	ssLayout->addSpacing(4);
+
 	ShadowVal = new ShadowValues( nullptr );
 	ShadowPop = new QMenu();
 	ShadowValAct = new QWidgetAction(this);
Index: scribus/ui/styleselect.h
===================================================================
--- scribus/ui/styleselect.h	(Revision 27090)
+++ scribus/ui/styleselect.h	(Arbeitskopie)
@@ -21,6 +21,7 @@
 
 #include "scrspinbox.h"
 #include "scribusapi.h"
+#include "ui/widgets/buttongroup.h"
 
 class SCRIBUS_API StrikeValues : public QFrame
 {
@@ -130,10 +131,10 @@
 	QHBoxLayout* ssLayout { nullptr };
 	QToolButton* underlineButton { nullptr };
 	QToolButton* underlineWordButton { nullptr };
-	QToolButton* subscriptButton { nullptr };
-	QToolButton* superscriptButton { nullptr };
-	QToolButton* smallcapsButton { nullptr };
-	QToolButton* allcapsButton { nullptr };
+	ToolButton* subscriptButton { nullptr };
+	ToolButton* superscriptButton { nullptr };
+	ToolButton* smallcapsButton { nullptr };
+	ToolButton* allcapsButton { nullptr };
 	QToolButton* strikeoutButton { nullptr };
 	QToolButton* outlineButton { nullptr };
 	QToolButton* shadowButton { nullptr };
buttongroup_2025-10-22_01.patch (27,204 bytes)   
files-2.zip (15,832 bytes)

Issue History

Date Modified Username Field Change
2025-07-04 21:26 nitramr New Issue
2025-07-04 21:26 nitramr Status new => assigned
2025-07-04 21:26 nitramr Assigned To => nitramr
2025-07-04 21:26 nitramr File Added: buttongroup_2025-07-04_01.patch
2025-07-04 21:26 nitramr File Added: files.zip
2025-07-04 21:26 nitramr File Added: preview.png
2025-07-06 17:08 jghali Note Added: 0052878
2025-07-06 17:17 jghali Note Added: 0052879
2025-07-06 17:17 jghali File Added: 17571_buttongroup_windows.png
2025-10-22 21:55 nitramr Note Added: 0053100
2025-10-22 21:55 nitramr File Added: buttongroup_2025-10-22_01.patch
2025-10-22 21:55 nitramr File Added: files-2.zip
2025-10-22 22:21 nitramr Relationship added related to 0017391