configure.ac                                      |    2 
 cui/Library_cui.mk                                |    5 
 cui/UIConfig_cui.mk                               |    2 
 cui/source/dialogs/welcomedlg.cxx                 |  106 ++++++++++++++
 cui/source/dialogs/whatsnewtabpage.cxx            |   89 ++++++++++++
 cui/source/factory/dlgfact.cxx                    |    6 
 cui/source/factory/dlgfact.hxx                    |    2 
 cui/source/inc/welcomedlg.hxx                     |   28 +++
 cui/source/inc/whatsnewtabpage.hxx                |   41 +++++
 cui/uiconfig/ui/welcomedialog.ui                  |  161 ++++++++++++++++++++++
 cui/uiconfig/ui/whatsnewtabpage.ui                |   28 +++
 icon-themes/colibre/brand/shell/animatedbrand.gif |binary
 include/sfx2/sfxdlg.hxx                           |    2 
 include/sfx2/sfxsids.hrc                          |    5 
 include/sfx2/strings.hrc                          |    6 
 sfx2/sdi/appslots.sdi                             |    4 
 sfx2/sdi/sfx.sdi                                  |   15 ++
 sfx2/source/appl/appserv.cxx                      |    7 
 sfx2/source/view/viewfrm.cxx                      |   10 +
 19 files changed, 514 insertions(+), 5 deletions(-)

New commits:
commit 9d90a1733bcf65763268583c97cd5e31a2f90f0c
Author:     Heiko Tietze <[email protected]>
AuthorDate: Tue Apr 15 09:22:55 2025 +0200
Commit:     Heiko Tietze <[email protected]>
CommitDate: Sun May 11 14:58:42 2025 +0200

    Resolves tdf#137931 - Show a Welcome dialog on first start-up
    
    With tabs for introduction (and later perhaps also as what's new
    info), appearance, and UI picker.
    
    Run ./soffice --safe-mode to test but make sure to start the app
    next in normal mode
    
    Change-Id: Ia12ba44c8796fb53f2ec1dbaf46dd25a6ec113cb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184195
    Tested-by: Jenkins
    Reviewed-by: Heiko Tietze <[email protected]>

diff --git a/configure.ac b/configure.ac
index 03d131053837..49d46418f947 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15115,7 +15115,7 @@ dnl 
===================================================================
 AC_MSG_CHECKING([for alternative branding images directory])
 # initialize mapped arrays
 BRAND_INTRO_IMAGES="intro.png intro-highres.png"
-brand_files="$BRAND_INTRO_IMAGES logo.svg logo_inverted.svg logo-sc.svg 
logo-sc_inverted.svg about.svg"
+brand_files="$BRAND_INTRO_IMAGES logo.svg logo_inverted.svg logo-sc.svg 
logo-sc_inverted.svg about.svg animatedbrand.gif"
 
 if test -z "$with_branding" -o "$with_branding" = "no"; then
     AC_MSG_RESULT([none])
diff --git a/cui/Library_cui.mk b/cui/Library_cui.mk
index cd540ab16a06..da1ad94c0608 100644
--- a/cui/Library_cui.mk
+++ b/cui/Library_cui.mk
@@ -161,7 +161,9 @@ $(eval $(call gb_Library_add_exception_objects,cui,\
     cui/source/dialogs/srchxtra \
     cui/source/dialogs/thesdlg \
     cui/source/dialogs/toolbarmodedlg \
+    cui/source/dialogs/whatsnewtabpage \
     cui/source/dialogs/uitabpage \
+    cui/source/dialogs/welcomedlg \
     cui/source/dialogs/zoom \
     cui/source/factory/cuiexp \
     cui/source/factory/cuiresmgr \
@@ -201,8 +203,7 @@ $(eval $(call gb_Library_add_exception_objects,cui,\
     cui/source/options/optpath \
     cui/source/options/optsave \
     cui/source/options/optupdt \
-    $(call gb_Helper_optional,DESKTOP,\
-        cui/source/options/appearance) \
+    cui/source/options/appearance \
     cui/source/options/sdbcdriverenum \
     cui/source/options/securityoptions \
     cui/source/options/treeopt \
diff --git a/cui/UIConfig_cui.mk b/cui/UIConfig_cui.mk
index f34f73abc750..cbafc04faf8e 100644
--- a/cui/UIConfig_cui.mk
+++ b/cui/UIConfig_cui.mk
@@ -230,6 +230,8 @@ $(eval $(call gb_UIConfig_add_uifiles,cui,\
        cui/uiconfig/ui/spinbox \
        cui/uiconfig/ui/zoomdialog \
        cui/uiconfig/ui/widgettestdialog \
+       cui/uiconfig/ui/welcomedialog \
+       cui/uiconfig/ui/whatsnewtabpage \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/cui/source/dialogs/welcomedlg.cxx 
b/cui/source/dialogs/welcomedlg.cxx
new file mode 100644
index 000000000000..6797affcbf58
--- /dev/null
+++ b/cui/source/dialogs/welcomedlg.cxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <welcomedlg.hxx>
+
+#include <whatsnewtabpage.hxx>
+#include <uitabpage.hxx>
+#include "../options/appearance.hxx"
+
+#include <comphelper/dispatchcommand.hxx>
+
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/sfxresid.hxx>
+#include <sfx2/strings.hrc>
+#include <sfx2/viewfrm.hxx>
+
+constexpr OUString sNewsTab = u"WhatsNewTabPage"_ustr;
+constexpr OUString sUITab = u"UITabPage"_ustr;
+constexpr OUString sAppearanceTab = u"AppearanceTabPage"_ustr;
+
+WelcomeDialog::WelcomeDialog(weld::Window* pParent)
+    : SfxTabDialogController(pParent, u"cui/ui/welcomedialog.ui"_ustr, 
u"WelcomeDialog"_ustr)
+    , m_xOKBtn(m_xBuilder->weld_button(u"ok"_ustr)) // release notes / apply
+    , m_xResetBtn(m_xBuilder->weld_button(u"reset"_ustr)) // hidden
+    , m_xCancelBtn(m_xBuilder->weld_button(u"cancel"_ustr)) // next / close
+{
+    m_xDialog->set_title(SfxResId(STR_WELCOME_LINE1));
+
+    AddTabPage(sNewsTab, WhatsNewTabPage::Create, nullptr);
+    AddTabPage(sUITab, UITabPage::Create, nullptr);
+    AddTabPage(sAppearanceTab, SvxAppearanceTabPage::Create, nullptr);
+
+    m_xTabCtrl->connect_enter_page(LINK(this, WelcomeDialog, OnActivatePage));
+    m_xResetBtn->set_visible(false);
+    m_xOKBtn->connect_clicked(LINK(this, WelcomeDialog, OnApplyClick));
+    m_xCancelBtn->connect_clicked(LINK(this, WelcomeDialog, OnNextClick));
+
+    m_xTabCtrl->set_current_page(sNewsTab);
+    OnActivatePage(sNewsTab);
+}
+
+IMPL_LINK(WelcomeDialog, OnActivatePage, const OUString&, rPage, void)
+{
+    if (rPage == sNewsTab)
+        m_xOKBtn->set_label(SfxResId(STR_CREDITS_BUTTON));
+    else
+        m_xOKBtn->set_label(SfxResId(STR_WELCOME_APPLY));
+
+    if (rPage == sAppearanceTab)
+        m_xCancelBtn->set_label(SfxResId(STR_WELCOME_CLOSE));
+    else
+        m_xCancelBtn->set_label(SfxResId(STR_WELCOME_NEXT));
+}
+
+IMPL_LINK_NOARG(WelcomeDialog, OnNextClick, weld::Button&, void)
+{
+    const int nCurrentTabPage(m_xTabCtrl->get_current_page());
+
+    if (nCurrentTabPage < 2)
+    {
+        m_xTabCtrl->set_current_page(nCurrentTabPage + 1);
+        OnActivatePage(m_xTabCtrl->get_page_ident(nCurrentTabPage + 1));
+    }
+    else
+        m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK_NOARG(WelcomeDialog, OnApplyClick, weld::Button&, void)
+{
+    switch (m_xTabCtrl->get_current_page())
+    {
+        case 0:
+        {
+            SfxViewFrame* pViewFrame = SfxViewFrame::Current();
+            if (pViewFrame)
+                
pViewFrame->GetBindings().GetDispatcher()->Execute(SID_CREDITS);
+        }
+        break;
+        case 1:
+        {
+            UITabPage* pUITabPage = static_cast<UITabPage*>(GetCurTabPage());
+            OUString sCmd = pUITabPage->GetSelectedMode();
+            comphelper::dispatchCommand(".uno:ToolbarMode?Mode:string=" + 
sCmd, {});
+        }
+        break;
+        case 2:
+        {
+            SvxAppearanceTabPage* pAppearanceTabPage
+                = static_cast<SvxAppearanceTabPage*>(GetCurTabPage());
+            pAppearanceTabPage->FillItemSet(nullptr);
+        }
+        break;
+        default:
+            m_xDialog->response(RET_OK);
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
\ No newline at end of file
diff --git a/cui/source/dialogs/whatsnewtabpage.cxx 
b/cui/source/dialogs/whatsnewtabpage.cxx
new file mode 100644
index 000000000000..128c4d765ff6
--- /dev/null
+++ b/cui/source/dialogs/whatsnewtabpage.cxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <whatsnewtabpage.hxx>
+
+#include <config_folders.h>
+#include <rtl/bootstrap.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/sfxresid.hxx>
+#include <sfx2/strings.hrc>
+#include <sfx2/viewfrm.hxx>
+#include <svx/dlgctrl.hxx>
+#include <vcl/graphicfilter.hxx>
+
+WhatsNewTabPage::WhatsNewTabPage(weld::Container* pPage, 
weld::DialogController* pController,
+                                 const SfxItemSet& rAttr)
+    : SfxTabPage(pPage, pController, u"cui/ui/whatsnewtabpage.ui"_ustr, 
u"WhatsNewTabPage"_ustr,
+                 &rAttr)
+    , m_aBrand()
+    , m_pBrand(new weld::CustomWeld(*m_xBuilder, u"imBrand"_ustr, m_aBrand))
+{
+    const Size aGraphicSize = m_aBrand.GetGraphicSize();
+    m_pBrand->set_size_request(aGraphicSize.getWidth(), 
aGraphicSize.getHeight());
+}
+
+std::unique_ptr<SfxTabPage> WhatsNewTabPage::Create(weld::Container* pPage,
+                                                    weld::DialogController* 
pController,
+                                                    const SfxItemSet* rAttr)
+{
+    return std::make_unique<WhatsNewTabPage>(pPage, pController, *rAttr);
+}
+
+AnimatedBrand::AnimatedBrand()
+{
+    OUString aURL(u"$BRAND_BASE_DIR/" LIBO_SHARE_SHELL_FOLDER 
"/animatedbrand.gif"_ustr);
+    rtl::Bootstrap::expandMacros(aURL);
+    GraphicFilter::LoadGraphic(aURL, OUString(), m_pGraphic);
+    m_pGraphicSize = m_pGraphic.GetSizePixel();
+}
+
+void AnimatedBrand::Paint(vcl::RenderContext& rRenderContext, const 
tools::Rectangle& rRect)
+{
+    //clear
+    rRenderContext.SetBackground(COL_WHITE);
+    rRenderContext.Erase();
+
+    const Point aGraphicPosition((rRect.GetWidth() - m_pGraphicSize.Width()),
+                                 (rRect.GetHeight() - m_pGraphicSize.Height()) 
>> 1);
+    if (m_pGraphic.IsAnimated() && MiscSettings::IsAnimatedOthersAllowed())
+        m_pGraphic.StartAnimation(rRenderContext, aGraphicPosition, 
m_pGraphicSize);
+    else
+        m_pGraphic.Draw(rRenderContext, aGraphicPosition, m_pGraphicSize);
+
+    tools::Rectangle aTextRect;
+    if (m_pGraphic.isAvailable())
+    {
+        aTextRect.SetPos(Point(8, 8));
+        aTextRect.SetSize(Size(aGraphicPosition.getX(), 
m_pGraphicSize.Height() - 20));
+    }
+    else
+        aTextRect = rRect;
+
+    //text
+    OUString sText(SfxResId(STR_WHATSNEW_FIRST));
+
+    vcl::Font aFont = rRenderContext.GetFont();
+    aFont.SetFontSize(Size(0, 24));
+    aFont.SetColor(COL_BLACK);
+    aFont.SetWeight(WEIGHT_BOLD);
+    rRenderContext.SetFont(aFont);
+
+    DrawTextFlags nDrawTextStyle(DrawTextFlags::MultiLine | 
DrawTextFlags::WordBreak
+                                 | DrawTextFlags::EndEllipsis);
+    const bool bIsRTL = rRenderContext.GetTextIsRTL(sText, 0, 
sText.getLength());
+    if (bIsRTL)
+        nDrawTextStyle |= DrawTextFlags::Right;
+
+    aTextRect.shrink(6);
+    aTextRect.setWidth(aTextRect.GetWidth() - 12);
+    rRenderContext.DrawText(aTextRect, sText, nDrawTextStyle);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
\ No newline at end of file
diff --git a/cui/source/factory/dlgfact.cxx b/cui/source/factory/dlgfact.cxx
index 34d735b8beb0..60c14b21c92d 100644
--- a/cui/source/factory/dlgfact.cxx
+++ b/cui/source/factory/dlgfact.cxx
@@ -99,6 +99,7 @@
 #include <fileextcheckdlg.hxx>
 #include <TextColumnsPage.hxx>
 #include <querydialog.hxx>
+#include <welcomedlg.hxx>
 
 #include <MacroManagerDialog.hxx>
 
@@ -1403,6 +1404,11 @@ public:
 };
 }
 
+VclPtr<SfxAbstractTabDialog> 
AbstractDialogFactory_Impl::CreateWelcomeDialog(weld::Window* pParent)
+{
+    return 
VclPtr<CuiAbstractTabController_Impl<WelcomeDialog>>::Create(pParent);
+}
+
 VclPtr<SfxAbstractPasteDialog> 
AbstractDialogFactory_Impl::CreatePasteDialog(weld::Window* pParent)
 {
     return VclPtr<AbstractPasteDialog_Impl>::Create(pParent);
diff --git a/cui/source/factory/dlgfact.hxx b/cui/source/factory/dlgfact.hxx
index 333b9f7fe230..b758e5ab90ff 100644
--- a/cui/source/factory/dlgfact.hxx
+++ b/cui/source/factory/dlgfact.hxx
@@ -181,6 +181,8 @@ public:
 
     virtual VclPtr<SfxAbstractTabDialog> 
CreateSvxFormatCellsDialog(weld::Window* pParent, const SfxItemSet& rAttr, 
const SdrModel& rModel, bool bStyle) override;
 
+    virtual VclPtr<SfxAbstractTabDialog> CreateWelcomeDialog(weld::Window* 
pParent) override;
+
     virtual VclPtr<SvxAbstractSplitTableDialog> 
CreateSvxSplitTableDialog(weld::Window* pParent, bool bIsTableVertical, 
tools::Long nMaxVertical) override;
 
     virtual std::shared_ptr<SvxAbstractNewTableDialog> 
CreateSvxNewTableDialog(weld::Window* pParent) override ;
diff --git a/cui/source/inc/welcomedlg.hxx b/cui/source/inc/welcomedlg.hxx
new file mode 100644
index 000000000000..a52af751da08
--- /dev/null
+++ b/cui/source/inc/welcomedlg.hxx
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+
+class WelcomeDialog : public SfxTabDialogController
+{
+private:
+    std::unique_ptr<weld::Button> m_xOKBtn; // release notes / apply
+    std::unique_ptr<weld::Button> m_xResetBtn; // hidden
+    std::unique_ptr<weld::Button> m_xCancelBtn; // next / close
+    DECL_LINK(OnActivatePage, const OUString&, void);
+    DECL_LINK(OnApplyClick, weld::Button&, void);
+    DECL_LINK(OnNextClick, weld::Button&, void);
+
+public:
+    WelcomeDialog(weld::Window* pParent);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/cui/source/inc/whatsnewtabpage.hxx 
b/cui/source/inc/whatsnewtabpage.hxx
new file mode 100644
index 000000000000..81d274a7c563
--- /dev/null
+++ b/cui/source/inc/whatsnewtabpage.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <vcl/customweld.hxx>
+#include <sfx2/tabdlg.hxx>
+#include <vcl/graph.hxx>
+
+class AnimatedBrand : public weld::CustomWidgetController
+{
+private:
+    Graphic m_pGraphic;
+    Size m_pGraphicSize;
+    virtual void Paint(vcl::RenderContext& rRenderContext, const 
tools::Rectangle&) override;
+
+public:
+    AnimatedBrand();
+    const Size& GetGraphicSize() const { return m_pGraphicSize; };
+};
+
+class WhatsNewTabPage : public SfxTabPage
+{
+private:
+    AnimatedBrand m_aBrand;
+    std::unique_ptr<weld::CustomWeld> m_pBrand;
+
+public:
+    WhatsNewTabPage(weld::Container* pPage, weld::DialogController* 
pController,
+                    const SfxItemSet& rSet);
+    static std::unique_ptr<SfxTabPage>
+    Create(weld::Container* pPage, weld::DialogController* pController, const 
SfxItemSet* rSet);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/cui/uiconfig/ui/welcomedialog.ui b/cui/uiconfig/ui/welcomedialog.ui
new file mode 100644
index 000000000000..0bf0072ebb7f
--- /dev/null
+++ b/cui/uiconfig/ui/welcomedialog.ui
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.40.0 -->
+<interface domain="cui">
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkDialog" id="WelcomeDialog">
+    <property name="can-focus">False</property>
+    <property name="border-width">6</property>
+    <property name="title" translatable="yes" 
context="welcomedialog|WelcomeDialog">What's new in %PRODUCTVERSION</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <property name="default-width">0</property>
+    <property name="default-height">0</property>
+    <property name="type-hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can-focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can-focus">False</property>
+            <property name="layout-style">end</property>
+            <child>
+              <object class="GtkButton" id="reset">
+                <property name="label" translatable="yes" 
context="stock">_Reset</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">True</property>
+                <property name="use-underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="ok">
+                <property name="label" translatable="yes" 
context="stock">_OK</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="can-default">True</property>
+                <property name="has-default">True</property>
+                <property name="receives-default">True</property>
+                <property name="use-underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="cancel">
+                <property name="label" translatable="yes" 
context="stock">_Close</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">True</property>
+                <property name="use-underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack-type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkNotebook" id="tabcontrol">
+            <property name="visible">True</property>
+            <property name="can-focus">True</property>
+            <child>
+              <!-- n-columns=1 n-rows=1 -->
+              <object class="GtkGrid">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+            </child>
+            <child type="tab">
+              <object class="GtkLabel" id="WhatsNewTabPage">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes" 
context="welcomedialog|whatsnewtab">What's New</property>
+              </object>
+              <packing>
+                <property name="tab-fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <!-- n-columns=1 n-rows=1 -->
+              <object class="GtkGrid">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child type="tab">
+              <object class="GtkLabel" id="UITabPage">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes" 
context="welcomedialog|uitab">User Interface</property>
+              </object>
+              <packing>
+                <property name="position">1</property>
+                <property name="tab-fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <!-- n-columns=1 n-rows=1 -->
+              <object class="GtkGrid">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child type="tab">
+              <object class="GtkLabel" id="AppearanceTabPage">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes" 
context="welcomedialog|appearancetab">Appearance</property>
+              </object>
+              <packing>
+                <property name="position">2</property>
+                <property name="tab-fill">False</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="101">reset</action-widget>
+      <action-widget response="-5">ok</action-widget>
+      <action-widget response="-7">cancel</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/cui/uiconfig/ui/whatsnewtabpage.ui 
b/cui/uiconfig/ui/whatsnewtabpage.ui
new file mode 100644
index 000000000000..56fafbaa4af1
--- /dev/null
+++ b/cui/uiconfig/ui/whatsnewtabpage.ui
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.40.0 -->
+<interface domain="cui">
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkBox" id="WhatsNewTabPage">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <property name="hexpand">True</property>
+    <property name="vexpand">True</property>
+    <property name="border-width">6</property>
+    <property name="spacing">6</property>
+    <child>
+      <object class="GtkDrawingArea" id="imBrand">
+        <property name="width-request">400</property>
+        <property name="height-request">400</property>
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/icon-themes/colibre/brand/shell/animatedbrand.gif 
b/icon-themes/colibre/brand/shell/animatedbrand.gif
new file mode 100644
index 000000000000..daf9efe40bd1
Binary files /dev/null and b/icon-themes/colibre/brand/shell/animatedbrand.gif 
differ
diff --git a/include/sfx2/sfxdlg.hxx b/include/sfx2/sfxdlg.hxx
index d5cf73b667bf..919ac744e212 100644
--- a/include/sfx2/sfxdlg.hxx
+++ b/include/sfx2/sfxdlg.hxx
@@ -167,6 +167,8 @@ public:
     virtual VclPtr<VclAbstractDialog> CreateToolbarmodeDialog(weld::Window* 
_pParent) = 0;
 
     virtual VclPtr<VclAbstractDialog> CreateWidgetTestDialog(weld::Window* 
_pParent) = 0;
+
+    virtual VclPtr<SfxAbstractTabDialog> CreateWelcomeDialog(weld::Window* 
pParent) =0;
 };
 
 #endif
diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc
index 2f02ef2d259d..3187a34fcced 100644
--- a/include/sfx2/sfxsids.hrc
+++ b/include/sfx2/sfxsids.hrc
@@ -117,8 +117,9 @@ class SvxZoomItem;
 #define SID_DOCUMENTATION                   (SID_SFX_START + 423)
 #define SID_DONATION                        (SID_SFX_START + 424)
 #define SID_GETINVOLVED                     (SID_SFX_START + 425)
-#define SID_WHATSNEW                        (SID_SFX_START + 426) // open 
ReleaseNotesURL
-#define SID_HYPHENATIONMISSING              (SID_SFX_START + 427)
+#define SID_WHATSNEW                        (SID_SFX_START + 426)
+#define SID_CREDITS                         (SID_SFX_START + 427)
+#define SID_HYPHENATIONMISSING              (SID_SFX_START + 428)
 
 #define SID_SHOW_LICENSE                    (SID_SFX_START + 1683)
 #define SID_SHOW_CREDITS                    (SID_SFX_START + 1711)
diff --git a/include/sfx2/strings.hrc b/include/sfx2/strings.hrc
index 6f5fc1211ae7..38d9aac4afc7 100644
--- a/include/sfx2/strings.hrc
+++ b/include/sfx2/strings.hrc
@@ -269,8 +269,14 @@
 #define STR_DONATE_TEXT                         NC_("STR_DONATE_TEXT", 
"Support the development of %PRODUCTNAME.")
 // Translators: text will be abbreviated at >8 characters, eg. "Please D..."
 #define STR_DONATE_BUTTON                       NC_("STR_DONATE_BUTTON", 
"Donate")
+#define STR_CREDITS_BUTTON                      NC_("STR_CREDITS_BUTTON", 
"Credits")
 #define STR_WHATSNEW_TEXT                       NC_("STR_WHATSNEW", "You are 
running version %PRODUCTVERSION of %PRODUCTNAME for the first time. Do you want 
to learn what's new?")
+#define STR_WHATSNEW_FIRST                      NC_("STR_WHATSNEWFIRST", "You 
are running %PRODUCTNAME for the first time.

Please take a moment to personalize your settings.")
 #define STR_WHATSNEW_BUTTON                     NC_("STR_WHATSNEW_BUTTON", 
"Release Notes")
+#define STR_WELCOME_APPLY                       NC_("STR_WELCOME_APPLY", 
"Apply")
+#define STR_WELCOME_CLOSE                       NC_("STR_WELCOME_CLOSE", 
"Close")
+#define STR_WELCOME_NEXT                        NC_("STR_WELCOME_NEXT", "Next")
+
 #define STR_READONLY_DOCUMENT                   NC_("STR_READONLY_DOCUMENT", 
"This document is open in read-only mode.")
 #define STR_READONLY_PDF                        NC_("STR_READONLY_PDF", "This 
PDF is open in read-only mode to allow signing the existing file.")
 #define STR_CLASSIFIED_DOCUMENT                 NC_("STR_CLASSIFIED_DOCUMENT", 
"The classification label of this document is %1.")
diff --git a/sfx2/sdi/appslots.sdi b/sfx2/sdi/appslots.sdi
index 47af19347cf4..905ee599ac33 100644
--- a/sfx2/sdi/appslots.sdi
+++ b/sfx2/sdi/appslots.sdi
@@ -152,6 +152,10 @@ interface Application
     [
         ExecMethod = MiscExec_Impl ;
     ]
+    SID_CREDITS
+    [
+        ExecMethod = MiscExec_Impl ;
+    ]
     SID_HYPHENATIONMISSING
     [
         ExecMethod = MiscExec_Impl ;
diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi
index c07d4bbf7a83..8ac9e5b8c6f1 100644
--- a/sfx2/sdi/sfx.sdi
+++ b/sfx2/sdi/sfx.sdi
@@ -5192,6 +5192,21 @@ SfxVoidItem WhatsNew SID_WHATSNEW
     MenuConfig = TRUE,
     GroupId = SfxGroupId::Application;
 ]
+SfxVoidItem Credits SID_CREDITS
+()
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = TRUE,
+    Toggle = FALSE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = TRUE,
+    MenuConfig = TRUE,
+    GroupId = SfxGroupId::Application;
+]
 SfxVoidItem HyphenationMissing SID_HYPHENATIONMISSING
 ()
 [
diff --git a/sfx2/source/appl/appserv.cxx b/sfx2/source/appl/appserv.cxx
index a814265bae5c..0e67e3e9374f 100644
--- a/sfx2/source/appl/appserv.cxx
+++ b/sfx2/source/appl/appserv.cxx
@@ -666,6 +666,13 @@ void SfxApplication::MiscExec_Impl( SfxRequest& rReq )
             sfx2::openUriExternally(sURL, false, rReq.GetFrameWeld());
             break;
         }
+        case SID_CREDITS:
+        {
+            OUString sURL(officecfg::Office::Common::Menus::CreditsURL::get());
+            sfx2::openUriExternally(sURL, false, rReq.GetFrameWeld());
+            break;
+        }
+        break;
         case SID_HYPHENATIONMISSING:
         {
             // Open wiki page about hyphenation
diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx
index 791996653298..ba07d0cd654e 100644
--- a/sfx2/source/view/viewfrm.cxx
+++ b/sfx2/source/view/viewfrm.cxx
@@ -24,6 +24,7 @@
 #include <osl/file.hxx>
 #include <sfx2/docfilt.hxx>
 #include <sfx2/infobar.hxx>
+#include <sfx2/sfxdlg.hxx>
 #include <sfx2/sfxsids.hrc>
 #include <sfx2/viewfrm.hxx>
 #include <sfx2/classificationhelper.hxx>
@@ -1644,6 +1645,15 @@ void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, 
const SfxHint& rHint )
 #if !ENABLE_WASM_STRIP_PINGUSER
                 if (!SfxApplication::IsHeadlessOrUITest()) //uitest.uicheck 
fails when the dialog is open
                 {
+                    static const bool bRunningUnitTest = 
o3tl::IsRunningUnitTest() || o3tl::IsRunningUITest();
+                    if (officecfg::Office::Common::Misc::FirstRun::get() && 
!IsInModalMode() && !bRunningUnitTest)
+                    {
+                        SfxAbstractDialogFactory* pFact = 
SfxAbstractDialogFactory::Create();
+                        ScopedVclPtr<SfxAbstractTabDialog> pDlg(
+                            
pFact->CreateWelcomeDialog(GetWindow().GetFrameWeld()));
+                        pDlg->Execute();
+                    }
+
                     bool bIsWhatsNewShown = false; //suppress tipoftheday if 
whatsnew was shown
 
                     //what's new dialog

Reply via email to