cui/source/options/appearance.cxx                          |   22 ++
 cui/source/options/appearance.hxx                          |    5 
 cui/uiconfig/ui/appearance.ui                              |  108 ++++++++++++-
 officecfg/registry/schema/org/openoffice/Office/Common.xcs |    7 
 vcl/source/window/builder.cxx                              |   15 +
 vcl/unx/gtk3/gtkinst.cxx                                   |    7 
 6 files changed, 153 insertions(+), 11 deletions(-)

New commits:
commit fc741371fa283036cdbd12be59c769c7cac39437
Author:     Heiko Tietze <tietze.he...@gmail.com>
AuthorDate: Wed Jul 9 13:00:23 2025 +0200
Commit:     Heiko Tietze <heiko.tie...@documentfoundation.org>
CommitDate: Wed Jul 9 15:52:08 2025 +0200

    Resolves tdf#167108 - Option to use horizontal tabs instead vertical
    
    Tabs with content (GtkBox with image/label) crash with the
    horizontal mode; avoid those UI variants and add tab pages per code
    
    Change-Id: I5908d6b2f62fed44ef69c313f3b8dc9d9f0a09d5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187565
    Tested-by: Jenkins
    Reviewed-by: Heiko Tietze <heiko.tie...@documentfoundation.org>

diff --git a/cui/source/options/appearance.cxx 
b/cui/source/options/appearance.cxx
index 14ee0f37ec46..388b2c836c32 100644
--- a/cui/source/options/appearance.cxx
+++ b/cui/source/options/appearance.cxx
@@ -124,10 +124,13 @@ 
SvxAppearanceTabPage::SvxAppearanceTabPage(weld::Container* pPage,
     , m_xSizeGrid(m_xBuilder->weld_widget(u"grdIconSize"_ustr))
     , m_xCustomizationFrame(m_xBuilder->weld_widget(u"items"_ustr))
     , m_sAutoStr(m_xIconsDropDown->get_text(0))
+    , m_xVerticalToolbars(m_xBuilder->weld_radio_button(u"rbVertical"_ustr))
+    , 
m_xHorizontalToolbars(m_xBuilder->weld_radio_button(u"rbHorizontal"_ustr))
 {
     InitThemes();
     InitCustomization();
     InitIcons();
+    InitDialogs();
 }
 
 void SvxAppearanceTabPage::LoadSchemeList()
@@ -575,6 +578,25 @@ void SvxAppearanceTabPage::InitIcons()
         m_xIconsDropDown->append(installIconTheme.GetThemeId(), 
installIconTheme.GetDisplayName());
 }
 
+void SvxAppearanceTabPage::InitDialogs()
+{
+    if (officecfg::Office::Common::Misc::UseVerticalNotebookbar::get())
+        m_xVerticalToolbars->set_active(true);
+    else
+        m_xHorizontalToolbars->set_active(true);
+
+    m_xVerticalToolbars->connect_toggled(LINK(this, SvxAppearanceTabPage, 
OnTabPosChange));
+}
+
+IMPL_LINK_NOARG(SvxAppearanceTabPage, OnTabPosChange, weld::Toggleable&, void)
+{
+    std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
+        comphelper::ConfigurationChanges::create());
+    bool bSet = m_xVerticalToolbars->get_active();
+    officecfg::Office::Common::Misc::UseVerticalNotebookbar::set(bSet, 
xChanges);
+    xChanges->commit();
+}
+
 IMPL_LINK_NOARG(SvxAppearanceTabPage, OnIconThemeChange, weld::ComboBox&, void)
 {
     std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
diff --git a/cui/source/options/appearance.hxx 
b/cui/source/options/appearance.hxx
index 4ab868e00c84..cb1d65faef0e 100644
--- a/cui/source/options/appearance.hxx
+++ b/cui/source/options/appearance.hxx
@@ -51,6 +51,8 @@ private:
     std::unique_ptr<weld::Widget> m_xSizeGrid;
     std::unique_ptr<weld::Widget> m_xCustomizationFrame;
     OUString m_sAutoStr;
+    std::unique_ptr<weld::RadioButton> m_xVerticalToolbars;
+    std::unique_ptr<weld::RadioButton> m_xHorizontalToolbars;
 
     sal_Int32 nInitialToolbarIconSizeSel;
     sal_Int32 nInitialSidebarIconSizeSel;
@@ -76,10 +78,13 @@ private:
     DECL_LINK(OnToolbarIconSizeChange, weld::ComboBox&, void);
     DECL_LINK(OnSidebarIconSizeChange, weld::ComboBox&, void);
     DECL_LINK(OnNotebookbarIconSizeChange, weld::ComboBox&, void);
+    DECL_LINK(OnTabPosChange, weld::Toggleable&, void);
 
     void InitThemes();
     void InitCustomization();
     void InitIcons();
+    void InitDialogs();
+
     void LoadSchemeList();
 
     void UpdateBmpControlsState();
diff --git a/cui/uiconfig/ui/appearance.ui b/cui/uiconfig/ui/appearance.ui
index 13a0e8dca2e6..6b1a8468b66d 100644
--- a/cui/uiconfig/ui/appearance.ui
+++ b/cui/uiconfig/ui/appearance.ui
@@ -12,7 +12,7 @@
     <property name="can-focus">False</property>
     <property name="icon-name">cmd/sc_additionsdialog.png</property>
   </object>
-  <!-- n-columns=1 n-rows=3 -->
+  <!-- n-columns=1 n-rows=4 -->
   <object class="GtkGrid" id="AppearanceTabPage">
     <property name="visible">True</property>
     <property name="can-focus">False</property>
@@ -103,11 +103,14 @@
                 <property name="row-spacing">3</property>
                 <property name="column-spacing">3</property>
                 <child>
-                  <object class="GtkLabel">
+                  <object class="GtkLabel" id="lbToolbar">
                     <property name="visible">True</property>
                     <property name="can-focus">False</property>
                     <property name="halign">start</property>
                     <property name="label" translatable="yes" 
context="appearance|toolbariconsizelbl">Toolbar</property>
+                    <accessibility>
+                      <relation type="label-for" 
target="toolbariconsdropdown"/>
+                    </accessibility>
                   </object>
                   <packing>
                     <property name="left-attach">0</property>
@@ -115,11 +118,14 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkLabel">
+                  <object class="GtkLabel" id="lbSidebar">
                     <property name="visible">True</property>
                     <property name="can-focus">False</property>
                     <property name="halign">start</property>
                     <property name="label" translatable="yes" 
context="appearance|sidebariconsizelbl">Sidebar</property>
+                    <accessibility>
+                      <relation type="label-for" 
target="sidebariconsdropdown"/>
+                    </accessibility>
                   </object>
                   <packing>
                     <property name="left-attach">0</property>
@@ -127,11 +133,14 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkLabel">
+                  <object class="GtkLabel" id="lbNotebookbar">
                     <property name="visible">True</property>
                     <property name="can-focus">False</property>
                     <property name="halign">start</property>
                     <property name="label" translatable="yes" 
context="appearance|notebookbariconsizelbl">Notebookbar</property>
+                    <accessibility>
+                      <relation type="label-for" 
target="notebookbariconsdropdown"/>
+                    </accessibility>
                   </object>
                   <packing>
                     <property name="left-attach">0</property>
@@ -148,6 +157,9 @@
                       <item translatable="yes" 
context="appearance|toolbariconsdropdown">Large</item>
                       <item translatable="yes" 
context="appearance|toolbariconsdropdown">Extra Large</item>
                     </items>
+                    <accessibility>
+                      <relation type="labelled-by" target="lbToolbar"/>
+                    </accessibility>
                     <child internal-child="accessible">
                       <object class="AtkObject" 
id="toolbariconsdropdown-atkobject">
                         <property name="AtkObject::accessible-description" 
translatable="yes" 
context="appearance|extended_tip|toolbariconsdropdown">Select the icon theme 
for the toolbar.</property>
@@ -168,6 +180,9 @@
                       <item translatable="yes" 
context="appearance|sidebariconsdropdown">Small</item>
                       <item translatable="yes" 
context="appearance|sidebariconsdropdown">Large</item>
                     </items>
+                    <accessibility>
+                      <relation type="labelled-by" target="lbSidebar"/>
+                    </accessibility>
                     <child internal-child="accessible">
                       <object class="AtkObject" 
id="sidebariconsdropdown-atkobject">
                         <property name="AtkObject::accessible-description" 
translatable="yes" 
context="appearance|extended_tip|sidebariconsdropdown">Select the icon theme 
for the sidebar.</property>
@@ -188,6 +203,9 @@
                       <item translatable="yes" 
context="appearance|notebookbariconsdropdown">Small</item>
                       <item translatable="yes" 
context="appearance|notebookbariconsdropdown">Large</item>
                     </items>
+                    <accessibility>
+                      <relation type="labelled-by" target="lbNotebookbar"/>
+                    </accessibility>
                     <child internal-child="accessible">
                       <object class="AtkObject" 
id="notebookbariconsdropdown-atkobject">
                         <property name="AtkObject::accessible-description" 
translatable="yes" 
context="appearance|extended_tip|notebookbariconsdropdown">Select the icon 
theme for the notebookbar.</property>
@@ -460,7 +478,6 @@
                 <property name="receives-default">True</property>
                 <property name="halign">start</property>
                 <property name="draw-indicator">True</property>
-                <property name="label" translatable="no"></property>
                 <child>
                   <placeholder/>
                 </child>
@@ -528,5 +545,86 @@
         <property name="top-attach">1</property>
       </packing>
     </child>
+    <child>
+      <object class="GtkFrame" id="dialogs">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="label-xalign">0</property>
+        <property name="shadow-type">none</property>
+        <child>
+          <!-- n-columns=3 n-rows=1 -->
+          <object class="GtkGrid">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="halign">start</property>
+            <property name="margin-start">12</property>
+            <property name="margin-top">6</property>
+            <child>
+              <object class="GtkRadioButton" id="rbVertical">
+                <property name="label" translatable="yes" 
context="appearance|rbVertical">Vertical at the side</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">False</property>
+                <property name="margin-start">6</property>
+                <property name="active">True</property>
+                <property name="draw-indicator">True</property>
+                <property name="group">rbHorizontal</property>
+                <accessibility>
+                  <relation type="labelled-by" target="lbTabPosition"/>
+                </accessibility>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="lbTabPosition">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes" 
context="appearance|lbTabPosition">Tab position:</property>
+                <property name="xalign">0</property>
+                <accessibility>
+                  <relation type="label-for" target="rbVertical"/>
+                </accessibility>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkRadioButton" id="rbHorizontal">
+                <property name="label" translatable="yes" 
context="appearance|rbHorizontal">Horizontal on top</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">False</property>
+                <property name="margin-start">6</property>
+                <property name="active">True</property>
+                <property name="draw-indicator">True</property>
+              </object>
+              <packing>
+                <property name="left-attach">2</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+        <child type="label">
+          <object class="GtkLabel" id="lbDialogs">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="label" translatable="yes" 
context="appearance|lbDialogs">Dialogs</property>
+            <attributes>
+              <attribute name="weight" value="bold"/>
+            </attributes>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="left-attach">0</property>
+        <property name="top-attach">3</property>
+      </packing>
+    </child>
   </object>
 </interface>
diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs 
b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
index 869790296884..91cf26ff39ce 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
@@ -5681,6 +5681,13 @@
         </info>
         <value>10</value>
       </prop>
+      <prop oor:name="UseVerticalNotebookbar" oor:type="xs:boolean" 
oor:nillable="false">
+        <info>
+          <desc>Defines whether to show tabs vertically or horizontallyin a 
notebookbar.</desc>
+          <label>Vertical tabs in dialogs</label>
+        </info>
+        <value>true</value>
+      </prop>
     </group>
     <group oor:name="Forms">
       <info>
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 3f47d02c2e65..cccb0c1c3c32 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -918,13 +918,18 @@ namespace
     bool extractVerticalTabPos(VclBuilder::stringmap &rMap)
     {
         bool bVertical = false;
-        VclBuilder::stringmap::iterator aFind = rMap.find(u"tab-pos"_ustr);
-        if (aFind != rMap.end())
+
+        if (officecfg::Office::Common::Misc::UseVerticalNotebookbar::get())
         {
-            bVertical = aFind->second.equalsIgnoreAsciiCase("left") ||
-                        aFind->second.equalsIgnoreAsciiCase("right");
-            rMap.erase(aFind);
+            VclBuilder::stringmap::iterator aFind = rMap.find(u"tab-pos"_ustr);
+            if (aFind != rMap.end())
+            {
+                bVertical = aFind->second.equalsIgnoreAsciiCase("left") ||
+                            aFind->second.equalsIgnoreAsciiCase("right");
+                rMap.erase(aFind);
+            }
         }
+
         return bVertical;
     }
 
diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index 72b4a7125d1d..14fedb9994f3 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -9057,7 +9057,9 @@ private:
         GtkWidget* pTabWidget = nullptr;
 
         GtkWidget* pImage = nullptr;
-        if (pIconName)
+        // do not show images of horizontal tabs
+        const bool bTabIsLeft = gtk_notebook_get_tab_pos(pNotebook) != 
GTK_POS_TOP;
+        if (pIconName && bTabIsLeft)
             pImage = image_new_from_icon_name(*pIconName);
 
         if (pImage)
@@ -9375,6 +9377,9 @@ public:
         }
         gtk_notebook_set_show_border(m_pOverFlowNotebook, false);
 
+        if (!officecfg::Office::Common::Misc::UseVerticalNotebookbar::get())
+            gtk_notebook_set_tab_pos(pNotebook, GTK_POS_TOP);
+
         // tdf#122623 it's nigh impossible to have a GtkNotebook without an 
active (checked) tab, so try and theme
         // the unwanted tab into invisibility via the 'overflow' class themed 
by global CreateStyleProvider
         GtkStyleContext *pNotebookContext = 
gtk_widget_get_style_context(GTK_WIDGET(m_pOverFlowNotebook));

Reply via email to