[Libreoffice-commits] core.git: Branch 'libreoffice-6-3' - cui/inc cui/source cui/uiconfig include/sfx2 include/vcl sfx2/source solenv/sanitizers vcl/Library_vcl.mk vcl/source vcl/uiconfig vcl/UIConfig_vcl.mk vcl/unx

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Thu Jun 6 15:31:07 UTC 2019


 cui/inc/strings.hrc               |   13 +
 cui/source/dialogs/about.cxx      |  215 +++++++++---------------
 cui/source/factory/dlgfact.cxx    |   10 -
 cui/source/factory/dlgfact.hxx    |    2 
 cui/source/inc/about.hxx          |   59 ++----
 cui/uiconfig/ui/aboutdialog.ui    |  328 +-------------------------------------
 include/sfx2/sfxdlg.hxx           |    1 
 include/vcl/aboutdialog.hxx       |   60 ++++++
 include/vcl/dialog.hxx            |    2 
 include/vcl/weld.hxx              |   17 +
 sfx2/source/appl/appserv.cxx      |    2 
 solenv/sanitizers/ui/cui.suppr    |   12 -
 solenv/sanitizers/ui/vcl.suppr    |   12 +
 vcl/Library_vcl.mk                |    1 
 vcl/UIConfig_vcl.mk               |    1 
 vcl/source/app/salvtables.cxx     |   79 +++++++++
 vcl/source/window/aboutdialog.cxx |  159 ++++++++++++++++++
 vcl/source/window/builder.cxx     |    8 
 vcl/uiconfig/ui/aboutbox.ui       |  135 +++++++++++++++
 vcl/unx/gtk3/gtk3gtkinst.cxx      |  178 ++++++++++++++++++++
 20 files changed, 784 insertions(+), 510 deletions(-)

New commits:
commit 06271aead1f262f2a76c8d4ed06500d9173f3ff4
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Tue Jun 4 11:34:28 2019 +0100
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Thu Jun 6 17:29:19 2019 +0200

    weld AboutDialog
    
    use a native GtkAboutDialog on that platform and refactor the current cui about
    dialog body to form the body of a vcl AboutDialog
    
    use add_button to add the buttons to whichever is preferred of the headerbar
    or action-area
    
    Change-Id: I67e0b36dcb8d3fa08ec4f0397b0f6185b0778675
    Reviewed-on: https://gerrit.libreoffice.org/73439
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit a30a5d1b8af18d19526f1980df41857f455cc8ef)
    Reviewed-on: https://gerrit.libreoffice.org/73583

diff --git a/cui/inc/strings.hrc b/cui/inc/strings.hrc
index 70aa6383149c..9b302e439453 100644
--- a/cui/inc/strings.hrc
+++ b/cui/inc/strings.hrc
@@ -391,6 +391,19 @@
 
 #define RID_SVXSTR_REGISTERED_DATABASES             NC_("RID_SVXSTR_REGISTERED_DATABASES", "Registered Databases")
 
+#define RID_SVXSTR_ABOUT_VERSION                    NC_("aboutdialog|textbuffer1", "Version: %ABOUTBOXPRODUCTVERSION%ABOUTBOXPRODUCTVERSIONSUFFIX")
+#define RID_SVXSTR_ABOUT_COPYRIGHT                  NC_("aboutdialog|copyright", "Copyright © 2000–2019 LibreOffice contributors.")
+#define RID_SVXSTR_ABOUT_CREDITS_URL                NC_("aboutdialog|link", "https://www.libreoffice.org/about-us/credits/")
+#define RID_SVXSTR_ABOUT_BUILDID                    NC_("aboutdialog|buildid", "Build ID: $BUILDID")
+#define RID_SVXSTR_ABOUT_VENDOR                     NC_("aboutdialog|vendor", "This release was supplied by %OOOVENDOR.")
+#define RID_SVXSTR_ABOUT_BASED_ON                   NC_("aboutdialog|libreoffice", "LibreOffice was based on OpenOffice.org.")
+#define RID_SVXSTR_ABOUT_DERIVED                    NC_("aboutdialog|derived", "%PRODUCTNAME is derived from LibreOffice which was based on OpenOffice.org")
+#define RID_SVXSTR_ABOUT_LOCALE                     NC_("aboutdialog|locale", "Locale: $LOCALE")
+#define RID_SVXSTR_ABOUT_UILOCALE                   NC_("aboutdialog|uilocale", "UI-Language: $LOCALE")
+#define RID_SVXSTR_ABOUT_RELEASE_NOTES              NC_("aboutdialog|releasenotes", "~Release Notes")
+#define RID_SVXSTR_ABOUT_WEBSITE                    NC_("aboutdialog|website", "~Website")
+#define RID_SVXSTR_ABOUT_CREDITS                    NC_("aboutdialog|credits", "Cre~dits")
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cui/source/dialogs/about.cxx b/cui/source/dialogs/about.cxx
index cdafad532c2c..776d89f9e88f 100644
--- a/cui/source/dialogs/about.cxx
+++ b/cui/source/dialogs/about.cxx
@@ -22,18 +22,19 @@
 #include <sal/log.hxx>
 #include <osl/diagnose.h>
 #include <rtl/character.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
 #include <vcl/layout.hxx>
-#include <vcl/weld.hxx>
-#include <vcl/svapp.hxx>
 #include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/weld.hxx>
 
 #include <tools/stream.hxx>
 #include <rtl/bootstrap.hxx>
 #include <unotools/configmgr.hxx>
 #include <unotools/bootstrap.hxx>
 #include <com/sun/star/uno/Any.h>
-#include <vcl/graph.hxx>
-#include <vcl/graphicfilter.hxx>
 #include <svtools/langhelp.hxx>
 #include <i18nlangtag/languagetag.hxx>
 
@@ -49,6 +50,8 @@
 
 #include <sfx2/sfxuno.hxx>
 #include <about.hxx>
+#include <dialmgr.hxx>
+#include <strings.hrc>
 #include <config_buildid.h>
 #include <sfx2/app.hxx>
 #include <rtl/ustrbuf.hxx>
@@ -64,80 +67,59 @@ using namespace ::com::sun::star::uno;
 using namespace ::com::sun::star::beans;
 using namespace ::com::sun::star;
 
-AboutDialog::AboutDialog(vcl::Window* pParent)
-    : SfxModalDialog(pParent, "AboutDialog", "cui/ui/aboutdialog.ui")
+AboutDialog::AboutDialog(weld::Window* pParent)
+    : m_xBuilder(Application::CreateBuilder(pParent, "cui/ui/aboutdialog.ui"))
+    , m_xDialog(m_xBuilder->weld_about_dialog("AboutDialog"))
+    , m_xContentArea(m_xDialog->weld_content_area())
 {
-    get(m_pLogoReplacement, "logoreplacement");
-    get(m_pLogoImage, "logo");
-    get(m_pVersion, "version");
-    get(m_pDescriptionText, "description");
-    get(m_pCopyrightText, "copyright");
-    get(m_pBuildIdLink, "buildIdLink");
-    m_aCopyrightTextStr = m_pCopyrightText->GetText();
-    get(m_pWebsiteButton, "website");
-    get(m_pCreditsButton, "credits");
-    get(m_pReleaseNotesButton, "btnReleaseNotes");
-    m_aCreditsLinkStr = get<FixedText>("link")->GetText();
-    m_sBuildStr = get<FixedText>("buildid")->GetText();
-    m_aVendorTextStr = get<FixedText>("vendor")->GetText();
-    m_aVersionTextStr = m_pVersion->GetText();
-    m_aBasedTextStr = get<FixedText>("libreoffice")->GetText();
-    m_aBasedDerivedTextStr = get<FixedText>("derived")->GetText();
-    m_aLocaleStr = get<FixedText>("locale")->GetText();
-    m_aUILocaleStr = get<FixedText>("uilocale")->GetText();
-    m_buildIdLinkString = m_pBuildIdLink->GetText();
-
-    m_pVersion->SetText(GetVersionString());
-
-    OUString aCopyrightString = GetCopyrightString();
-    m_pCopyrightText->SetText( aCopyrightString );
+    m_xDialog->add_button(Button::GetStandardText(StandardButtonType::Close), RET_CLOSE);
+    m_xDialog->add_button(CuiResId(RID_SVXSTR_ABOUT_CREDITS), 101);
+    m_xDialog->add_button(CuiResId(RID_SVXSTR_ABOUT_WEBSITE), 102);
+    m_xDialog->add_button(CuiResId(RID_SVXSTR_ABOUT_RELEASE_NOTES), 103);
 
-    SetBuildIdLink();
+    m_pCreditsButton = m_xDialog->get_widget_for_response(101);
+    m_pCreditsButton->set_secondary(true);
+    m_pWebsiteButton = m_xDialog->get_widget_for_response(102);
+    m_pWebsiteButton->set_secondary(true);
+    m_pReleaseNotesButton = m_xDialog->get_widget_for_response(103);
+    m_pReleaseNotesButton->set_secondary(true);
+    m_pCloseButton = m_xDialog->get_widget_for_response(RET_CLOSE);
+
+    m_buildIdLinkString = m_xDialog->get_website_label();
 
-    StyleControls();
+    m_xDialog->set_version(GetVersionString());
+    m_xDialog->set_copyright(GetCopyrightString());
+
+    SetBuildIdLink();
 
     SetLogo();
 
-    // Connect all handlers
-    m_pCreditsButton->SetClickHdl( LINK( this, AboutDialog, HandleClick ) );
-    m_pWebsiteButton->SetClickHdl( LINK( this, AboutDialog, HandleClick ) );
-    m_pReleaseNotesButton->SetClickHdl( LINK( this, AboutDialog, HandleClick ) );
+    m_xDialog->connect_size_allocate(LINK(this, AboutDialog, SizeAllocHdl));
 
-    get<PushButton>("close")->GrabFocus();
+    // Connect all handlers
+    m_pCreditsButton->connect_clicked( LINK( this, AboutDialog, HandleClick ) );
+    m_pWebsiteButton->connect_clicked( LINK( this, AboutDialog, HandleClick ) );
+    m_pReleaseNotesButton->connect_clicked( LINK( this, AboutDialog, HandleClick ) );
+    m_pCloseButton->grab_focus();
 }
 
 AboutDialog::~AboutDialog()
 {
-    disposeOnce();
-}
-
-void AboutDialog::dispose()
-{
-    m_pVersion.clear();
-    m_pDescriptionText.clear();
-    m_pCopyrightText.clear();
-    m_pLogoImage.clear();
-    m_pLogoReplacement.clear();
-    m_pCreditsButton.clear();
-    m_pWebsiteButton.clear();
-    m_pBuildIdLink.clear();
-    m_pReleaseNotesButton.clear();
-    SfxModalDialog::dispose();
 }
 
-IMPL_LINK( AboutDialog, HandleClick, Button*, pButton, void )
+IMPL_LINK(AboutDialog, HandleClick, weld::Button&, rButton, void)
 {
     OUString sURL = "";
 
     // Find which button was pressed and from this, get the URL to be opened
-    if (pButton == m_pCreditsButton)
-        sURL = m_aCreditsLinkStr;
-    else if (pButton == m_pWebsiteButton)
+    if (&rButton == m_pCreditsButton)
+        sURL = CuiResId(RID_SVXSTR_ABOUT_CREDITS_URL);
+    else if (&rButton == m_pWebsiteButton)
     {
         sURL = officecfg::Office::Common::Help::StartCenter::InfoURL::get();
         localizeWebserviceURI(sURL);
     }
-    else if (pButton == m_pReleaseNotesButton)
+    else if (&rButton == m_pReleaseNotesButton)
     {
         sURL = officecfg::Office::Common::Menus::ReleaseNotesURL::get() +
                "?LOvers=" + utl::ConfigManager::getProductVersion() +
@@ -158,9 +140,9 @@ IMPL_LINK( AboutDialog, HandleClick, Button*, pButton, void )
         Any exc( ::cppu::getCaughtException() );
         OUString msg( ::comphelper::anyToString( exc ) );
         const SolarMutexGuard guard;
-        std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(pButton->GetFrameWeld(),
+        std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(getDialog(),
                                                        VclMessageType::Warning, VclButtonsType::Ok, msg));
-        xErrorBox->set_title(GetText());
+        xErrorBox->set_title(m_xDialog->get_title());
         xErrorBox->run();
     }
 }
@@ -177,41 +159,19 @@ void AboutDialog::SetBuildIdLink()
             m_buildIdLinkString += " $GITHASH";
         }
 
-        m_pBuildIdLink->SetText(m_buildIdLinkString.replaceAll("$GITHASH", buildId));
-        m_pBuildIdLink->SetURL("https://hub.libreoffice.org/git-core/" + buildId);
+        m_xDialog->set_website_label(m_buildIdLinkString.replaceAll("$GITHASH", buildId));
+        m_xDialog->set_website("https://hub.libreoffice.org/git-core/" + buildId);
     }
     else
     {
-        m_pBuildIdLink->Hide();
+        m_xDialog->set_website_label(OUString());
+        m_xDialog->set_website(OUString());
     }
 }
 
-void AboutDialog::StyleControls()
-{
-    // Make all the controls have a transparent background
-    m_pLogoImage->SetBackground();
-    m_pLogoReplacement->SetPaintTransparent(true);
-    m_pVersion->SetPaintTransparent(true);
-    m_pDescriptionText->SetPaintTransparent(true);
-    m_pCopyrightText->SetPaintTransparent(true);
-
-    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
-
-    const vcl::Font& aLabelFont = rStyleSettings.GetLabelFont();
-    vcl::Font aLargeFont = aLabelFont;
-    aLargeFont.SetFontSize(Size( 0, aLabelFont.GetFontSize().Height() * 3));
-
-    // Logo Replacement Text
-    m_pLogoReplacement->SetControlFont(aLargeFont);
-
-    // Description Text
-    aLargeFont.SetFontSize(Size(0, aLabelFont.GetFontSize().Height() * 1.3));
-    m_pDescriptionText->SetControlFont(aLargeFont);
-}
-
 void AboutDialog::SetLogo()
 {
-    long nWidth = get_content_area()->get_preferred_size().Width();
+    auto nWidth = m_xContentArea->get_preferred_size().Width();
 
     // fdo#67401 set AntiAliasing for SVG logo
     SvtOptionsDrawinglayer aDrawOpt;
@@ -219,43 +179,36 @@ void AboutDialog::SetLogo()
     aDrawOpt.SetAntiAliasing(true);
 
     // load svg logo, specify desired width, scale height isotropically
-    if (SfxApplication::loadBrandSvg("flat_logo", aLogoBitmap, nWidth) &&
-        !aLogoBitmap.IsEmpty())
-    {
-        m_pLogoImage->SetImage(Image(aLogoBitmap));
-        m_pLogoReplacement->Hide();
-        m_pLogoImage->Show();
-    }
+    SfxApplication::loadBrandSvg("flat_logo", aLogoBitmap, nWidth);
+
+    aDrawOpt.SetAntiAliasing(bOldAntiAliasSetting);
+
+    if (!aLogoBitmap)
+        m_xDialog->set_logo(nullptr);
     else
     {
-        m_pLogoImage->Hide();
-        m_pLogoReplacement->Show();
+        ScopedVclPtr<VirtualDevice> xDevice(m_xDialog->create_virtual_device());
+        xDevice->SetOutputSize(aLogoBitmap.GetSizePixel());
+        xDevice->DrawBitmapEx(Point(), aLogoBitmap);
+        m_xDialog->set_logo(xDevice.get());
     }
-    aDrawOpt.SetAntiAliasing(bOldAntiAliasSetting);
 }
 
-void AboutDialog::Resize()
+IMPL_LINK(AboutDialog, SizeAllocHdl, const Size&, rSize, void)
 {
-    SfxModalDialog::Resize();
-
+    if (rSize.Width() == aBackgroundBitmap.GetSizePixel().Width())
+        return;
     // Load background image
-    if (isInitialLayout(this) && !(Application::GetSettings().GetStyleSettings().GetHighContrastMode()))
+    if (!(Application::GetSettings().GetStyleSettings().GetHighContrastMode()))
     {
-        SfxApplication::loadBrandSvg("shell/about", aBackgroundBitmap, GetSizePixel().Width());
+        SfxApplication::loadBrandSvg("shell/about", aBackgroundBitmap, rSize.Width());
+        ScopedVclPtr<VirtualDevice> xDevice(m_xDialog->create_virtual_device());
+        xDevice->SetOutputSize(aBackgroundBitmap.GetSizePixel());
+        xDevice->DrawBitmapEx(Point(), aBackgroundBitmap);
+        m_xDialog->set_background(xDevice.get());
     }
 }
 
-void AboutDialog::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect)
-{
-    rRenderContext.SetClipRegion(vcl::Region(rRect));
-
-    Size aSize(GetOutputSizePixel());
-    Point aPos(aSize.Width() - aBackgroundBitmap.GetSizePixel().Width(),
-               aSize.Height() - aBackgroundBitmap.GetSizePixel().Height());
-
-    rRenderContext.DrawBitmapEx(aPos, aBackgroundBitmap);
-}
-
 OUString AboutDialog::GetBuildId()
 {
     OUString sDefault;
@@ -309,7 +262,7 @@ bool AboutDialog::IsStringValidGitHash(const OUString& hash)
 
 OUString AboutDialog::GetVersionString()
 {
-    OUString sVersion = m_aVersionTextStr;
+    OUString sVersion = CuiResId(RID_SVXSTR_ABOUT_VERSION);
 
 #ifdef _WIN64
     sVersion += " (x64)";
@@ -325,12 +278,13 @@ OUString AboutDialog::GetVersionString()
     if (!sBuildId.trim().isEmpty())
     {
         sVersion += "\n";
-        if (m_sBuildStr.indexOf("$BUILDID") == -1)
+        OUString sBuildStr = CuiResId(RID_SVXSTR_ABOUT_BUILDID);
+        if (sBuildStr.indexOf("$BUILDID") == -1)
         {
             SAL_WARN( "cui.dialogs", "translated Build Id string in translations doesn't contain $BUILDID placeholder" );
-            m_sBuildStr += " $BUILDID";
+            sBuildStr += " $BUILDID";
         }
-        sVersion += m_sBuildStr.replaceAll("$BUILDID", sBuildId);
+        sVersion += sBuildStr.replaceAll("$BUILDID", sBuildId);
     }
 
     sVersion += "\n" + Application::GetHWOSConfInfo();
@@ -342,19 +296,21 @@ OUString AboutDialog::GetVersionString()
         sVersion += "\n" EXTRA_BUILDID;
     }
 
-    if (m_aLocaleStr.indexOf("$LOCALE") == -1)
+    OUString sLocaleStr(CuiResId(RID_SVXSTR_ABOUT_LOCALE));
+    if (sLocaleStr.indexOf("$LOCALE") == -1)
     {
         SAL_WARN( "cui.dialogs", "translated locale string in translations doesn't contain $LOCALE placeholder" );
-        m_aLocaleStr += " $LOCALE";
+        sLocaleStr += " $LOCALE";
     }
-    sVersion += "\n" + m_aLocaleStr.replaceAll("$LOCALE", aLocaleStr);
+    sVersion += "\n" + sLocaleStr.replaceAll("$LOCALE", aLocaleStr);
 
-    if (m_aUILocaleStr.indexOf("$LOCALE") == -1)
+    OUString sUILocaleStr(CuiResId(RID_SVXSTR_ABOUT_UILOCALE));
+    if (sUILocaleStr.indexOf("$LOCALE") == -1)
     {
         SAL_WARN( "cui.dialogs", "translated uilocale string in translations doesn't contain $LOCALE placeholder" );
-        m_aUILocaleStr += " $LOCALE";
+        sUILocaleStr += " $LOCALE";
     }
-    sVersion += "; " + m_aUILocaleStr.replaceAll("$LOCALE", aUILocaleStr);
+    sVersion += "; " + sUILocaleStr.replaceAll("$LOCALE", aUILocaleStr);
 
     OUString aCalcMode = "Calc: "; // Calc calculation mode
 
@@ -383,21 +339,16 @@ OUString AboutDialog::GetVersionString()
 
 OUString AboutDialog::GetCopyrightString()
 {
-    OUString aCopyrightString  = m_aVendorTextStr + "\n"
-                               + m_aCopyrightTextStr + "\n";
+    OUString sVendorTextStr(CuiResId(RID_SVXSTR_ABOUT_VENDOR));
+    OUString aCopyrightString  = sVendorTextStr + "\n"
+                               + CuiResId(RID_SVXSTR_ABOUT_COPYRIGHT) + "\n";
 
     if (utl::ConfigManager::getProductName() == "LibreOffice")
-        aCopyrightString += m_aBasedTextStr;
+        aCopyrightString += CuiResId(RID_SVXSTR_ABOUT_BASED_ON);
     else
-        aCopyrightString += m_aBasedDerivedTextStr;
+        aCopyrightString += CuiResId(RID_SVXSTR_ABOUT_DERIVED);
 
     return aCopyrightString;
 }
 
-bool AboutDialog::Close()
-{
-    EndDialog( RET_OK );
-    return false;
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cui/source/factory/dlgfact.cxx b/cui/source/factory/dlgfact.cxx
index 17f8c137c2a4..0c1fbe4612c8 100644
--- a/cui/source/factory/dlgfact.cxx
+++ b/cui/source/factory/dlgfact.cxx
@@ -925,11 +925,6 @@ VclPtr<VclAbstractDialog> AbstractDialogFactory_Impl::CreateVclDialog( vcl::Wind
     VclPtr<Dialog> pDlg;
     switch ( nResId )
     {
-        case SID_ABOUT:
-        {
-            pDlg = VclPtr<AboutDialog>::Create(pParent);
-            break;
-        }
         case SID_OPTIONS_TREEDIALOG :
         case SID_OPTIONS_DATABASES :
         case SID_LANGUAGE_OPTIONS :
@@ -960,6 +955,11 @@ VclPtr<VclAbstractDialog> AbstractDialogFactory_Impl::CreateVclDialog( vcl::Wind
     return nullptr;
 }
 
+VclPtr<VclAbstractDialog> AbstractDialogFactory_Impl::CreateAboutDialog(weld::Window* pParent)
+{
+    return VclPtr<CuiAbstractController_Impl>::Create(std::make_unique<AboutDialog>(pParent));
+}
+
 VclPtr<VclAbstractDialog> AbstractDialogFactory_Impl::CreateFrameDialog(vcl::Window* pParent, const Reference< frame::XFrame >& rxFrame,
     sal_uInt32 nResId, const OUString& rParameter )
 {
diff --git a/cui/source/factory/dlgfact.hxx b/cui/source/factory/dlgfact.hxx
index 6623de48ab6a..58548d82463b 100644
--- a/cui/source/factory/dlgfact.hxx
+++ b/cui/source/factory/dlgfact.hxx
@@ -685,6 +685,8 @@ class AbstractDialogFactory_Impl : public SvxAbstractDialogFactory
 public:
     virtual VclPtr<VclAbstractDialog>    CreateVclDialog( vcl::Window* pParent, sal_uInt32 nResId ) override;
 
+    virtual VclPtr<VclAbstractDialog>    CreateAboutDialog(weld::Window* pParent) override;
+
     virtual VclPtr<SfxAbstractDialog>    CreateSfxDialog( weld::Window* pParent,
                                             const SfxItemSet& rAttr,
                                             const SdrView* pView,
diff --git a/cui/source/inc/about.hxx b/cui/source/inc/about.hxx
index d191343f941a..cabfc3eb652f 100644
--- a/cui/source/inc/about.hxx
+++ b/cui/source/inc/about.hxx
@@ -19,67 +19,44 @@
 #ifndef INCLUDED_CUI_SOURCE_INC_ABOUT_HXX
 #define INCLUDED_CUI_SOURCE_INC_ABOUT_HXX
 
-#include <vcl/accel.hxx>
-#include <vcl/button.hxx>
-#include <vcl/fixed.hxx>
-#include <vcl/fixedhyper.hxx>
-#include <vcl/vclmedit.hxx>
-#include <sfx2/basedlgs.hxx>
-#include <vector>
+#include <vcl/weld.hxx>
 
-// class AboutDialog -----------------------------------------------------
-
-class AboutDialog : public SfxModalDialog
+class AboutDialog : public weld::DialogController
 {
 private:
-    BitmapEx           aBackgroundBitmap;
-    BitmapEx           aLogoBitmap;
+    std::unique_ptr<weld::Builder> m_xBuilder;
+    std::shared_ptr<weld::AboutDialog> m_xDialog;
+    std::shared_ptr<weld::Container> m_xContentArea;
 
-    VclPtr<VclMultiLineEdit>    m_pVersion;
-    VclPtr<FixedHyperlink>      m_pBuildIdLink;
-    VclPtr<FixedText>           m_pDescriptionText;
-    VclPtr<FixedText>           m_pCopyrightText;
-    VclPtr<FixedImage>          m_pLogoImage;
-    VclPtr<FixedText>           m_pLogoReplacement;
-    VclPtr<PushButton>          m_pCreditsButton;
-    VclPtr<PushButton>          m_pWebsiteButton;
-    VclPtr<PushButton>          m_pReleaseNotesButton;
+    BitmapEx           aLogoBitmap;
+    BitmapEx           aBackgroundBitmap;
 
-    OUString m_aVersionTextStr;
-    OUString m_aVendorTextStr;
-    OUString m_aCopyrightTextStr;
-    OUString m_aBasedTextStr;
-    OUString m_aBasedDerivedTextStr;
-    OUString m_aCreditsLinkStr;
-    OUString m_sBuildStr;
-    OUString m_aLocaleStr;
-    OUString m_aUILocaleStr;
     OUString m_buildIdLinkString;
 
+    weld::Button* m_pCreditsButton;
+    weld::Button* m_pWebsiteButton;
+    weld::Button* m_pReleaseNotesButton;
+    weld::Button* m_pCloseButton;
+
     void SetBuildIdLink();
     void StyleControls();
     void SetLogo();
 
     static OUString GetBuildId();
-    OUString GetVersionString();
-    OUString GetCopyrightString();
+    static OUString GetVersionString();
+    static OUString GetCopyrightString();
     static OUString GetLocaleString();
     static bool IsStringValidGitHash(const OUString& hash);
 
-protected:
-    virtual bool Close() override;
-    virtual void Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect) override;
-    virtual void Resize() override;
-
 public:
-    AboutDialog(vcl::Window* pParent);
+    AboutDialog(weld::Window* pParent);
+    virtual weld::Dialog* getDialog() override { return m_xDialog.get(); }
     virtual ~AboutDialog() override;
-    virtual void dispose() override;
 
-    DECL_LINK( HandleClick, Button*, void );
+    DECL_LINK(HandleClick, weld::Button&, void);
+    DECL_LINK(SizeAllocHdl, const Size&, void);
 };
 
 #endif // INCLUDED_CUI_SOURCE_INC_ABOUT_HXX
 
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cui/uiconfig/ui/aboutdialog.ui b/cui/uiconfig/ui/aboutdialog.ui
index a85bcc66b322..07f2be7e3e06 100644
--- a/cui/uiconfig/ui/aboutdialog.ui
+++ b/cui/uiconfig/ui/aboutdialog.ui
@@ -2,15 +2,21 @@
 <!-- Generated with glade 3.22.1 -->
 <interface domain="cui">
   <requires lib="gtk+" version="3.18"/>
-  <object class="GtkTextBuffer" id="textbuffer1">
-    <property name="text" translatable="yes" context="aboutdialog|textbuffer1">Version: %ABOUTBOXPRODUCTVERSION%ABOUTBOXPRODUCTVERSIONSUFFIX</property>
-  </object>
-  <object class="GtkDialog" id="AboutDialog">
+  <object class="GtkAboutDialog" id="AboutDialog">
     <property name="can_focus">False</property>
-    <property name="border_width">6</property>
-    <property name="title" translatable="yes" context="aboutdialog|AboutDialog">About %PRODUCTNAME</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>
+    <property name="title" translatable="yes" context="aboutdialog|AboutDialog">About %PRODUCTNAME</property>
+    <property name="program_name">%PRODUCTNAME</property>
+    <property name="comments" translatable="yes" context="aboutdialog|description">%PRODUCTNAME is a modern, easy-to-use, open source productivity suite for word processing, spreadsheets, presentations and more.</property>
+    <property name="website">https://www.libreoffice.org/</property>
+    <property name="website_label" translatable="yes" context="aboutdialog|buildIdLink">See Log: $GITHASH</property>
+    <property name="logo_icon_name">image-missing</property>
+    <child>
+      <placeholder/>
+    </child>
     <child internal-child="vbox">
       <object class="GtkBox" id="dialog-vbox1">
         <property name="can_focus">False</property>
@@ -18,68 +24,11 @@
         <property name="spacing">12</property>
         <child internal-child="action_area">
           <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="layout_style">end</property>
             <child>
-              <object class="GtkButton" id="btnReleaseNotes">
-                <property name="label" translatable="yes" context="aboutdialog|releasenotes">_Release Notes</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">0</property>
-                <property name="secondary">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="credits">
-                <property name="label" translatable="yes" context="aboutdialog|credits">Cre_dits</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">1</property>
-                <property name="secondary">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="website">
-                <property name="label" translatable="yes" context="aboutdialog|website">_Website</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>
-                <property name="secondary">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="close">
-                <property name="label">gtk-close</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_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">3</property>
-              </packing>
+              <placeholder/>
             </child>
           </object>
           <packing>
@@ -89,254 +38,7 @@
             <property name="position">0</property>
           </packing>
         </child>
-        <child>
-          <object class="GtkBox" id="box1">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="hexpand">True</property>
-            <property name="vexpand">True</property>
-            <property name="orientation">vertical</property>
-            <property name="spacing">12</property>
-            <child>
-              <object class="GtkImage" id="logo">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="stock">gtk-missing-image</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkBox" id="box2">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="hexpand">True</property>
-                <property name="vexpand">True</property>
-                <property name="orientation">vertical</property>
-                <property name="spacing">12</property>
-                <child>
-                  <object class="GtkLabel" id="logoreplacement">
-                    <property name="can_focus">False</property>
-                    <property name="no_show_all">True</property>
-                    <property name="label" translatable="yes" context="aboutdialog|logoreplacement">%PRODUCTNAME</property>
-                    <property name="justify">center</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkGrid" id="grid1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="hexpand">True</property>
-                    <child>
-                      <object class="GtkLabel" id="buildid">
-                        <property name="can_focus">False</property>
-                        <property name="no_show_all">True</property>
-                        <property name="hexpand">True</property>
-                        <property name="label" translatable="yes" context="aboutdialog|buildid">Build ID: $BUILDID</property>
-                        <property name="justify">center</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="locale">
-                        <property name="can_focus">False</property>
-                        <property name="no_show_all">True</property>
-                        <property name="hexpand">True</property>
-                        <property name="label" translatable="yes" context="aboutdialog|locale">Locale: $LOCALE</property>
-                        <property name="justify">center</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkTextView" id="version">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="hexpand">True</property>
-                        <property name="editable">False</property>
-                        <property name="wrap_mode">word</property>
-                        <property name="justification">center</property>
-                        <property name="cursor_visible">False</property>
-                        <property name="buffer">textbuffer1</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="uilocale">
-                        <property name="can_focus">False</property>
-                        <property name="no_show_all">True</property>
-                        <property name="hexpand">True</property>
-                        <property name="label" translatable="yes" context="aboutdialog|locale">UI-Language: $LOCALE</property>
-                        <property name="justify">center</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">3</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLinkButton" id="buildIdLink">
-                    <property name="label" translatable="yes" context="aboutdialog|buildIdLink">See Log: $GITHASH</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="relief">none</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="description">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="hexpand">True</property>
-                    <property name="label" translatable="yes" context="aboutdialog|description">%PRODUCTNAME is a modern, easy-to-use, open source productivity suite for word processing, spreadsheets, presentations and more.</property>
-                    <property name="justify">center</property>
-                    <property name="wrap">True</property>
-                    <property name="max_width_chars">62</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">3</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkGrid" id="grid2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="hexpand">True</property>
-                    <child>
-                      <object class="GtkLabel" id="copyright">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="margin_left">12</property>
-                        <property name="margin_right">12</property>
-                        <property name="hexpand">True</property>
-                        <property name="label" translatable="yes" context="aboutdialog|copyright">Copyright © 2000–2019 LibreOffice contributors.</property>
-                        <property name="justify">center</property>
-                        <property name="wrap">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="libreoffice">
-                        <property name="can_focus">False</property>
-                        <property name="no_show_all">True</property>
-                        <property name="hexpand">True</property>
-                        <property name="label" translatable="yes" context="aboutdialog|libreoffice">LibreOffice was based on OpenOffice.org.</property>
-                        <property name="justify">center</property>
-                        <property name="wrap">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="derived">
-                        <property name="can_focus">False</property>
-                        <property name="no_show_all">True</property>
-                        <property name="hexpand">True</property>
-                        <property name="label" translatable="yes" context="aboutdialog|derived">%PRODUCTNAME is derived from LibreOffice which was based on OpenOffice.org.</property>
-                        <property name="justify">center</property>
-                        <property name="wrap">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="vendor">
-                        <property name="can_focus">False</property>
-                        <property name="no_show_all">True</property>
-                        <property name="hexpand">True</property>
-                        <property name="label" translatable="yes" context="aboutdialog|vendor">This release was supplied by %OOOVENDOR.</property>
-                        <property name="justify">center</property>
-                        <property name="wrap">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">0</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">4</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="link">
-                    <property name="can_focus">False</property>
-                    <property name="no_show_all">True</property>
-                    <property name="label" translatable="yes" context="aboutdialog|link">https://www.libreoffice.org/about-us/credits/</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">5</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
       </object>
     </child>
-    <action-widgets>
-      <action-widget response="101">btnReleaseNotes</action-widget>
-      <action-widget response="102">credits</action-widget>
-      <action-widget response="103">website</action-widget>
-      <action-widget response="-7">close</action-widget>
-    </action-widgets>
-  </object>
-  <object class="GtkSizeGroup" id="sizegroup1">
-    <widgets>
-      <widget name="copyright"/>
-      <widget name="libreoffice"/>
-      <widget name="vendor"/>
-    </widgets>
   </object>
 </interface>
diff --git a/include/sfx2/sfxdlg.hxx b/include/sfx2/sfxdlg.hxx
index 2250bd07bf96..ad71369ba961 100644
--- a/include/sfx2/sfxdlg.hxx
+++ b/include/sfx2/sfxdlg.hxx
@@ -132,6 +132,7 @@ public:
     virtual VclPtr<SfxAbstractPasteDialog>    CreatePasteDialog(weld::Window* pParent) = 0;
     virtual VclPtr<SfxAbstractLinksDialog>    CreateLinksDialog(weld::Window* pParent, sfx2::LinkManager* pMgr, bool bHTML=false, sfx2::SvBaseLink* p=nullptr) = 0;
     virtual VclPtr<VclAbstractDialog>         CreateSvxScriptOrgDialog(weld::Window* pParent,  const OUString& rLanguage) = 0;
+    virtual VclPtr<VclAbstractDialog>         CreateAboutDialog(weld::Window* pParent) = 0;
 
     virtual VclPtr<AbstractScriptSelectorDialog> CreateScriptSelectorDialog(weld::Window* pParent,
             const css::uno::Reference< css::frame::XFrame >& rxFrame) = 0;
diff --git a/include/vcl/aboutdialog.hxx b/include/vcl/aboutdialog.hxx
new file mode 100644
index 000000000000..4126f9519a1b
--- /dev/null
+++ b/include/vcl/aboutdialog.hxx
@@ -0,0 +1,60 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_VCL_ABOUT_DIALOG_HXX
+#define INCLUDED_VCL_ABOUT_DIALOG_HXX
+
+#include <vcl/button.hxx>
+#include <vcl/fixed.hxx>
+#include <vcl/fixedhyper.hxx>
+#include <vcl/dialog.hxx>
+#include <vcl/layout.hxx>
+#include <vcl/vclmedit.hxx>
+
+class AboutDialog : public Dialog
+{
+private:
+    BitmapEx m_aBackgroundBitmap;
+
+    std::unique_ptr<VclBuilder> m_xBuilder;
+    VclPtr<VclContainer> m_xContents;
+    VclPtr<VclMultiLineEdit> m_xVersion;
+    VclPtr<FixedHyperlink> m_xBuildIdLink;
+    VclPtr<FixedText> m_xDescriptionText;
+    VclPtr<FixedText> m_xCopyrightText;
+    VclPtr<FixedImage> m_xLogoImage;
+    VclPtr<FixedText> m_xLogoReplacement;
+
+    void StyleControls();
+
+protected:
+    virtual void Paint(vcl::RenderContext& rRenderContext,
+                       const ::tools::Rectangle& rRect) override;
+    virtual bool set_property(const OString& rKey, const OUString& rValue) override;
+    virtual void set_content_area(VclBox* pBox) override;
+
+public:
+    explicit AboutDialog(vcl::Window* pParent, WinBits nStyle = WB_STDDIALOG,
+                         InitFlag eFlag = InitFlag::Default);
+    virtual ~AboutDialog() override;
+    virtual void dispose() override;
+
+    void SetLogo(const Image& rLogoBitmap);
+    void SetBackground(const Image& rBackgroundBitmap);
+    void SetVersion(const OUString& rVersion) { m_xVersion->SetText(rVersion); }
+    void SetCopyright(const OUString& rCopyright) { m_xCopyrightText->SetText(rCopyright); }
+    void SetWebsiteLink(const OUString& rURL) { m_xBuildIdLink->SetURL(rURL); }
+    void SetWebsiteLabel(const OUString& rLabel) { m_xBuildIdLink->SetText(rLabel); }
+
+    OUString GetWebsiteLabel() const { return m_xBuildIdLink->GetText(); }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index 3748dbd943d5..32b06be57db9 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -96,7 +96,7 @@ protected:
 protected:
     friend class VclBuilder;
     void set_action_area(VclButtonBox* pBox);
-    void set_content_area(VclBox* pBox);
+    virtual void set_content_area(VclBox* pBox);
 
 public:
     explicit        Dialog( vcl::Window* pParent, WinBits nStyle = WB_STDDIALOG, InitFlag eFlag = InitFlag::Default );
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 19c808b2b9d5..768750142eb5 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -129,6 +129,8 @@ public:
     virtual void set_vexpand(bool bExpand) = 0;
     virtual bool get_vexpand() const = 0;
 
+    virtual void set_secondary(bool bSecondary) = 0;
+
     virtual void set_margin_top(int nMargin) = 0;
     virtual void set_margin_bottom(int nMargin) = 0;
 
@@ -433,6 +435,18 @@ public:
     virtual Container* weld_message_area() = 0;
 };
 
+class VCL_DLLPUBLIC AboutDialog : virtual public Dialog
+{
+public:
+    virtual void set_version(const OUString& rVersion) = 0;
+    virtual void set_copyright(const OUString& rCopyright) = 0;
+    virtual void set_website(const OUString& rURL) = 0;
+    virtual void set_website_label(const OUString& rLabel) = 0;
+    virtual OUString get_website_label() const = 0;
+    virtual void set_logo(VirtualDevice* pDevice) = 0;
+    virtual void set_background(VirtualDevice* pDevice) = 0;
+};
+
 struct VCL_DLLPUBLIC ComboBoxEntry
 {
     OUString sString;
@@ -1730,6 +1744,9 @@ public:
                                                                bool bTakeOwnership = true)
         = 0;
     virtual std::unique_ptr<Dialog> weld_dialog(const OString& id, bool bTakeOwnership = true) = 0;
+    virtual std::unique_ptr<AboutDialog> weld_about_dialog(const OString& id,
+                                                           bool bTakeOwnership = true)
+        = 0;
     virtual std::unique_ptr<Window> weld_window(const OString& id, bool bTakeOwnership = true) = 0;
     virtual std::unique_ptr<Widget> weld_widget(const OString& id, bool bTakeOwnership = false) = 0;
     virtual std::unique_ptr<Container> weld_container(const OString& id,
diff --git a/sfx2/source/appl/appserv.cxx b/sfx2/source/appl/appserv.cxx
index c5f09027700c..a7707b791867 100644
--- a/sfx2/source/appl/appserv.cxx
+++ b/sfx2/source/appl/appserv.cxx
@@ -673,7 +673,7 @@ void SfxApplication::MiscExec_Impl( SfxRequest& rReq )
         case SID_ABOUT:
         {
             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
-            ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog( nullptr, SID_ABOUT ));
+            ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateAboutDialog(rReq.GetFrameWeld()));
             pDlg->Execute();
             bDone = true;
             break;
diff --git a/solenv/sanitizers/ui/cui.suppr b/solenv/sanitizers/ui/cui.suppr
index d5edb8af2f96..3e7bee42463c 100644
--- a/solenv/sanitizers/ui/cui.suppr
+++ b/solenv/sanitizers/ui/cui.suppr
@@ -1,15 +1,3 @@
-cui/uiconfig/ui/aboutdialog.ui://GtkImage[@id='logo'] no-labelled-by
-cui/uiconfig/ui/aboutdialog.ui://GtkLabel[@id='logoreplacement'] orphan-label
-cui/uiconfig/ui/aboutdialog.ui://GtkLabel[@id='buildid'] orphan-label
-cui/uiconfig/ui/aboutdialog.ui://GtkLabel[@id='locale'] orphan-label
-cui/uiconfig/ui/aboutdialog.ui://GtkLabel[@id='uilocale'] orphan-label
-cui/uiconfig/ui/aboutdialog.ui://GtkTextView[@id='version'] no-labelled-by
-cui/uiconfig/ui/aboutdialog.ui://GtkLabel[@id='description'] orphan-label
-cui/uiconfig/ui/aboutdialog.ui://GtkLabel[@id='copyright'] orphan-label
-cui/uiconfig/ui/aboutdialog.ui://GtkLabel[@id='libreoffice'] orphan-label
-cui/uiconfig/ui/aboutdialog.ui://GtkLabel[@id='derived'] orphan-label
-cui/uiconfig/ui/aboutdialog.ui://GtkLabel[@id='vendor'] orphan-label
-cui/uiconfig/ui/aboutdialog.ui://GtkLabel[@id='link'] orphan-label
 cui/uiconfig/ui/aboutconfigdialog.ui://GtkEntry[@id='searchEntry'] no-labelled-by
 cui/uiconfig/ui/aboutconfigdialog.ui://GtkLabel[@id='preference'] orphan-label
 cui/uiconfig/ui/aboutconfigdialog.ui://GtkLabel[@id='property'] orphan-label
diff --git a/solenv/sanitizers/ui/vcl.suppr b/solenv/sanitizers/ui/vcl.suppr
index b103ac934ee4..f3a4c670cc97 100644
--- a/solenv/sanitizers/ui/vcl.suppr
+++ b/solenv/sanitizers/ui/vcl.suppr
@@ -1,3 +1,15 @@
+vcl/uiconfig/ui/aboutbox.ui://GtkImage[@id='logo'] no-labelled-by
+vcl/uiconfig/ui/aboutbox.ui://GtkLabel[@id='logoreplacement'] orphan-label
+vcl/uiconfig/ui/aboutbox.ui://GtkLabel[@id='buildid'] orphan-label
+vcl/uiconfig/ui/aboutbox.ui://GtkLabel[@id='locale'] orphan-label
+vcl/uiconfig/ui/aboutbox.ui://GtkLabel[@id='uilocale'] orphan-label
+vcl/uiconfig/ui/aboutbox.ui://GtkTextView[@id='version'] no-labelled-by
+vcl/uiconfig/ui/aboutbox.ui://GtkLabel[@id='description'] orphan-label
+vcl/uiconfig/ui/aboutbox.ui://GtkLabel[@id='copyright'] orphan-label
+vcl/uiconfig/ui/aboutbox.ui://GtkLabel[@id='libreoffice'] orphan-label
+vcl/uiconfig/ui/aboutbox.ui://GtkLabel[@id='derived'] orphan-label
+vcl/uiconfig/ui/aboutbox.ui://GtkLabel[@id='vendor'] orphan-label
+vcl/uiconfig/ui/aboutbox.ui://GtkLabel[@id='link'] orphan-label
 vcl/uiconfig/ui/cupspassworddialog.ui://GtkLabel[@id='text'] orphan-label
 vcl/uiconfig/ui/printdialog.ui://GtkSpinButton[@id='pageedit-nospin'] no-labelled-by
 vcl/uiconfig/ui/printdialog.ui://GtkLabel[@id='totalnumpages'] orphan-label
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 428e69324782..deb7cf049106 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -117,6 +117,7 @@ endif
 $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/animate/Animation \
     vcl/source/animate/AnimationBitmap \
+    vcl/source/window/aboutdialog \
     vcl/source/window/errinf \
     vcl/source/window/settings \
     vcl/source/window/paint \
diff --git a/vcl/UIConfig_vcl.mk b/vcl/UIConfig_vcl.mk
index 8a385dedddd8..3184aaee5293 100644
--- a/vcl/UIConfig_vcl.mk
+++ b/vcl/UIConfig_vcl.mk
@@ -10,6 +10,7 @@
 $(eval $(call gb_UIConfig_UIConfig,vcl))
 
 $(eval $(call gb_UIConfig_add_uifiles,vcl,\
+	vcl/uiconfig/ui/aboutbox \
 	vcl/uiconfig/ui/cupspassworddialog \
 	vcl/uiconfig/ui/editmenu \
 	vcl/uiconfig/ui/errornocontentdialog \
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index afca107ef91c..166a5133feb0 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -36,6 +36,7 @@
 #include <unotools/accessiblerelationsethelper.hxx>
 #include <utility>
 #include <tools/helpers.hxx>
+#include <vcl/aboutdialog.hxx>
 #include <vcl/builder.hxx>
 #include <vcl/calendar.hxx>
 #include <vcl/combobox.hxx>
@@ -462,6 +463,11 @@ public:
         return m_xWidget->get_vexpand();
     }
 
+    virtual void set_secondary(bool bSecondary) override
+    {
+        m_xWidget->set_secondary(bSecondary);
+    }
+
     virtual void set_margin_top(int nMargin) override
     {
         m_xWidget->set_margin_top(nMargin);
@@ -1301,6 +1307,26 @@ public:
         VclPtr<PushButton> xButton(VclPtr<PushButton>::Create(pBox, WB_CLIPCHILDREN|WB_CENTER|WB_VCENTER));
         xButton->SetText(rText);
         xButton->SetHelpId(rHelpId);
+
+        switch (nResponse)
+        {
+            case RET_OK:
+                xButton->set_id("ok");
+                break;
+            case RET_CLOSE:
+                xButton->set_id("close");
+                break;
+            case RET_CANCEL:
+                xButton->set_id("cancel");
+                break;
+            case RET_YES:
+                xButton->set_id("yes");
+                break;
+            case RET_NO:
+                xButton->set_id("no");
+                break;
+        }
+
         xButton->Show();
         m_xDialog->add_button(xButton, nResponse, true);
     }
@@ -1355,6 +1381,46 @@ public:
     }
 };
 
+class SalInstanceAboutDialog : public SalInstanceDialog, public virtual weld::AboutDialog
+{
+private:
+    VclPtr<::AboutDialog> m_xAboutDialog;
+public:
+    SalInstanceAboutDialog(::AboutDialog* pDialog, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
+        : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership)
+        , m_xAboutDialog(pDialog)
+    {
+    }
+    virtual void set_version(const OUString& rVersion) override
+    {
+        m_xAboutDialog->SetVersion(rVersion);
+    }
+    virtual void set_copyright(const OUString& rCopyright) override
+    {
+        m_xAboutDialog->SetCopyright(rCopyright);
+    }
+    virtual void set_website(const OUString& rURL) override
+    {
+        m_xAboutDialog->SetWebsiteLink(rURL);
+    }
+    virtual void set_website_label(const OUString& rLabel) override
+    {
+        m_xAboutDialog->SetWebsiteLabel(rLabel);
+    }
+    virtual OUString get_website_label() const override
+    {
+        return m_xAboutDialog->GetWebsiteLabel();
+    }
+    virtual void set_logo(VirtualDevice* pDevice) override
+    {
+        m_xAboutDialog->SetLogo(createImage(*pDevice));
+    }
+    virtual void set_background(VirtualDevice* pDevice) override
+    {
+        m_xAboutDialog->SetBackground(createImage(*pDevice));
+    }
+};
+
 class SalInstanceFrame : public SalInstanceContainer, public virtual weld::Frame
 {
 private:
@@ -5014,6 +5080,19 @@ public:
         return pRet;
     }
 
+    virtual std::unique_ptr<weld::AboutDialog> weld_about_dialog(const OString &id, bool bTakeOwnership) override
+    {
+        AboutDialog* pAboutDialog = m_xBuilder->get<AboutDialog>(id);
+        std::unique_ptr<weld::AboutDialog> pRet(pAboutDialog ? new SalInstanceAboutDialog(pAboutDialog, this, false) : nullptr);
+        if (bTakeOwnership && pAboutDialog)
+        {
+            assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
+            m_aOwnedToplevel.set(pAboutDialog);
+            m_xBuilder->drop_ownership(pAboutDialog);
+        }
+        return pRet;
+    }
+
     virtual std::unique_ptr<weld::Dialog> weld_dialog(const OString &id, bool bTakeOwnership) override
     {
         Dialog* pDialog = m_xBuilder->get<Dialog>(id);
diff --git a/vcl/source/window/aboutdialog.cxx b/vcl/source/window/aboutdialog.cxx
new file mode 100644
index 000000000000..1a563dfd367d
--- /dev/null
+++ b/vcl/source/window/aboutdialog.cxx
@@ -0,0 +1,159 @@
+/* -*- 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 <config_features.h>
+#include <osl/process.h>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <rtl/character.hxx>
+#include <vcl/aboutdialog.hxx>
+#include <vcl/layout.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+#include <tools/stream.hxx>
+#include <rtl/bootstrap.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/bootstrap.hxx>
+#include <com/sun/star/uno/Any.h>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
+#include <com/sun/star/system/SystemShellExecute.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/bootstrap.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <com/sun/star/geometry/RealRectangle2D.hpp>
+
+#include <config_buildid.h>
+#include <rtl/ustrbuf.hxx>
+#include <vcl/bitmap.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star;
+
+AboutDialog::AboutDialog(vcl::Window* pParent, WinBits nStyle, Dialog::InitFlag eFlag)
+    : Dialog(pParent, nStyle, eFlag)
+    , m_xBuilder(new VclBuilder(this, getUIRootDir(), "vcl/ui/aboutbox.ui"))
+{
+    m_xBuilder->get(m_xContents, "about");
+    m_xBuilder->get(m_xLogoReplacement, "logoreplacement");
+    m_xBuilder->get(m_xLogoImage, "logo");
+    m_xBuilder->get(m_xVersion, "version");
+    m_xBuilder->get(m_xDescriptionText, "description");
+    m_xBuilder->get(m_xCopyrightText, "copyright");
+    m_xBuilder->get(m_xBuildIdLink, "buildIdLink");
+}
+
+void AboutDialog::set_content_area(VclBox* pBox)
+{
+    Dialog::set_content_area(pBox);
+
+    // move it now that the content area exists
+    m_xContents->SetParent(pBox);
+
+    StyleControls();
+}
+
+AboutDialog::~AboutDialog() { disposeOnce(); }
+
+void AboutDialog::dispose()
+{
+    m_xVersion.clear();
+    m_xDescriptionText.clear();
+    m_xCopyrightText.clear();
+    m_xLogoImage.clear();
+    m_xLogoReplacement.clear();
+    m_xBuildIdLink.clear();
+    m_xContents.clear();
+    m_xBuilder.reset();
+    Dialog::dispose();
+}
+
+void AboutDialog::StyleControls()
+{
+    // Make all the controls have a transparent background
+    m_xLogoImage->SetBackground();
+    m_xLogoReplacement->SetPaintTransparent(true);
+    m_xVersion->SetPaintTransparent(true);
+    m_xDescriptionText->SetPaintTransparent(true);
+    m_xCopyrightText->SetPaintTransparent(true);
+
+    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+
+    const vcl::Font& aLabelFont = rStyleSettings.GetLabelFont();
+    vcl::Font aLargeFont = aLabelFont;
+    aLargeFont.SetFontSize(Size(0, aLabelFont.GetFontSize().Height() * 3));
+
+    // Logo Replacement Text
+    m_xLogoReplacement->SetControlFont(aLargeFont);
+
+    // Description Text
+    aLargeFont.SetFontSize(Size(0, aLabelFont.GetFontSize().Height() * 1.3));
+    m_xDescriptionText->SetControlFont(aLargeFont);
+}
+
+void AboutDialog::SetLogo(const Image& rLogoBitmap)
+{
+    if (!rLogoBitmap)
+    {
+        m_xLogoImage->Hide();
+        m_xLogoReplacement->Show();
+    }
+    else
+    {
+        m_xLogoReplacement->Hide();
+        m_xLogoImage->SetImage(rLogoBitmap);
+        m_xLogoImage->Show();
+    }
+}
+
+void AboutDialog::SetBackground(const Image& rBackgroundBitmap)
+{
+    m_aBackgroundBitmap = rBackgroundBitmap.GetBitmapEx();
+    Invalidate();
+}
+
+void AboutDialog::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect)
+{
+    rRenderContext.SetClipRegion(vcl::Region(rRect));
+
+    Size aSize(GetOutputSizePixel());
+    Point aPos(aSize.Width() - m_aBackgroundBitmap.GetSizePixel().Width(),
+               aSize.Height() - m_aBackgroundBitmap.GetSizePixel().Height());
+
+    rRenderContext.DrawBitmapEx(aPos, m_aBackgroundBitmap);
+}
+
+bool AboutDialog::set_property(const OString& rKey, const OUString& rValue)
+{
+    if (rKey == "version")
+        m_xVersion->SetText(rValue);
+    else if (rKey == "copyright")
+        m_xCopyrightText->SetText(rValue);
+    else if (rKey == "comments")
+        m_xDescriptionText->SetText(rValue);
+    else if (rKey == "website")
+        m_xBuildIdLink->SetURL(rValue);
+    else if (rKey == "website_label")
+        m_xBuildIdLink->SetText(rValue);
+    else if (rKey == "program_name")
+        m_xLogoReplacement->SetText(rValue);
+    else
+        return Dialog::set_property(rKey, rValue);
+    return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 42c6654c5e64..61df46ffe9b7 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -20,6 +20,7 @@
 #include <sal/log.hxx>
 #include <unotools/localedatawrapper.hxx>
 #include <unotools/resmgr.hxx>
+#include <vcl/aboutdialog.hxx>
 #include <vcl/builder.hxx>
 #include <vcl/builderfactory.hxx>
 #include <vcl/button.hxx>
@@ -1647,12 +1648,15 @@ VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString &
     extractButtonImage(id, rMap, name == "GtkRadioButton");
 
     VclPtr<vcl::Window> xWindow;
-    if (name == "GtkDialog")
+    if (name == "GtkDialog" || name == "GtkAboutDialog")
     {
         WinBits nBits = WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE;
         if (extractResizable(rMap))
             nBits |= WB_SIZEABLE;
-        xWindow = VclPtr<Dialog>::Create(pParent, nBits, !pParent ? Dialog::InitFlag::NoParent : Dialog::InitFlag::Default);
+        if (name == "GtkAboutDialog")
+            xWindow = VclPtr<AboutDialog>::Create(pParent, nBits, !pParent ? Dialog::InitFlag::NoParent : Dialog::InitFlag::Default);
+        else
+            xWindow = VclPtr<Dialog>::Create(pParent, nBits, !pParent ? Dialog::InitFlag::NoParent : Dialog::InitFlag::Default);
 #if HAVE_FEATURE_DESKTOP
         if (!m_bLegacy && !extractModal(rMap))
             xWindow->SetType(WindowType::MODELESSDIALOG);
diff --git a/vcl/uiconfig/ui/aboutbox.ui b/vcl/uiconfig/ui/aboutbox.ui
new file mode 100644
index 000000000000..2686d80e675a
--- /dev/null
+++ b/vcl/uiconfig/ui/aboutbox.ui
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="cui">
+  <requires lib="gtk+" version="3.18"/>
+  <object class="GtkBox" id="about">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="hexpand">True</property>
+    <property name="vexpand">True</property>
+    <property name="orientation">vertical</property>
+    <property name="spacing">12</property>
+    <child>
+      <object class="GtkImage" id="logo">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="stock">gtk-missing-image</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="box2">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkLabel" id="logoreplacement">
+            <property name="can_focus">False</property>
+            <property name="no_show_all">True</property>
+            <property name="justify">center</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid" id="grid1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <child>
+              <object class="GtkTextView" id="version">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="editable">False</property>
+                <property name="wrap_mode">word</property>
+                <property name="justification">center</property>
+                <property name="cursor_visible">False</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLinkButton" id="buildIdLink">
+            <property name="label" translatable="yes" context="aboutdialog|buildIdLink">See Log: $GITHASH</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="relief">none</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="description">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="justify">center</property>
+            <property name="wrap">True</property>
+            <property name="max_width_chars">62</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid" id="grid2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <child>
+              <object class="GtkLabel" id="copyright">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_left">12</property>
+                <property name="margin_right">12</property>
+                <property name="hexpand">True</property>
+                <property name="justify">center</property>
+                <property name="wrap">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">4</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index bd1f8a6f3abe..eb1511d5f53a 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -1817,6 +1817,13 @@ public:
         return gtk_widget_get_vexpand(m_pWidget);
     }
 
+    virtual void set_secondary(bool bSecondary) override
+    {
+        GtkWidget* pParent = gtk_widget_get_parent(m_pWidget);
+        if (pParent && GTK_IS_BUTTON_BOX(pParent))
+            gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(pParent), m_pWidget, bSecondary);
+    }
+
     virtual void set_margin_top(int nMargin) override
     {
         gtk_widget_set_margin_top(m_pWidget, nMargin);
@@ -2288,10 +2295,31 @@ namespace
     GdkPixbuf* getPixbuf(const VirtualDevice& rDevice)
     {
         Size aSize(rDevice.GetOutputSizePixel());
-        cairo_surface_t* surface = get_underlying_cairo_surface(rDevice);
+        cairo_surface_t* orig_surface = get_underlying_cairo_surface(rDevice);
         double m_fXScale, m_fYScale;
-        dl_cairo_surface_get_device_scale(surface, &m_fXScale, &m_fYScale);
-        return gdk_pixbuf_get_from_surface(surface, 0, 0, aSize.Width() * m_fXScale, aSize.Height() * m_fYScale);
+        dl_cairo_surface_get_device_scale(orig_surface, &m_fXScale, &m_fYScale);
+
+        cairo_surface_t* surface;
+        if (m_fXScale != 1.0 || m_fYScale != -1)
+        {
+            surface = cairo_surface_create_similar_image(orig_surface,
+                                                         CAIRO_FORMAT_ARGB32,
+                                                         aSize.Width(),
+                                                         aSize.Height());
+            cairo_t* cr = cairo_create(surface);
+            cairo_set_source_surface(cr, orig_surface, 0, 0);
+            cairo_paint(cr);
+            cairo_destroy(cr);
+        }
+        else
+            surface = orig_surface;
+
+        GdkPixbuf* pRet = gdk_pixbuf_get_from_surface(surface, 0, 0, aSize.Width(), aSize.Height());
+
+        if (surface != orig_surface)
+            cairo_surface_destroy(surface);
+
+        return pRet;
     }
 
     GtkWidget* image_new_from_virtual_device(const VirtualDevice& rImageSurface)
@@ -3349,6 +3377,123 @@ public:
     }
 };
 
+class GtkInstanceAboutDialog : public GtkInstanceDialog, public virtual weld::AboutDialog
+{
+private:
+    GtkAboutDialog* m_pAboutDialog;
+    GtkCssProvider* m_pCssProvider;
+    std::unique_ptr<utl::TempFile>  mxBackgroundImage;
+public:
+    GtkInstanceAboutDialog(GtkAboutDialog* pAboutDialog, GtkInstanceBuilder* pBuilder, bool bTakeOwnership)
+        : GtkInstanceDialog(GTK_DIALOG(pAboutDialog), pBuilder, bTakeOwnership)
+        , m_pAboutDialog(pAboutDialog)
+        , m_pCssProvider(nullptr)
+    {
+        // in GtkAboutDialog apply_use_header_bar if headerbar is false it
+        // automatically adds a default close button which it doesn't if
+        // headerbar is true and which doesn't appear in the .ui
+        if (GtkWidget* pDefaultButton = gtk_dialog_get_widget_for_response(GTK_DIALOG(pAboutDialog), GTK_RESPONSE_DELETE_EVENT))
+            gtk_widget_destroy(pDefaultButton);
+    }
+
+    virtual void set_version(const OUString& rVersion) override
+    {
+        gtk_about_dialog_set_version(m_pAboutDialog, OUStringToOString(rVersion, RTL_TEXTENCODING_UTF8).getStr());
+    }
+
+    virtual void set_copyright(const OUString& rCopyright) override
+    {
+        gtk_about_dialog_set_copyright(m_pAboutDialog, OUStringToOString(rCopyright, RTL_TEXTENCODING_UTF8).getStr());
+    }
+
+    virtual void set_website(const OUString& rURL) override
+    {
+        OString sURL(OUStringToOString(rURL, RTL_TEXTENCODING_UTF8));
+        gtk_about_dialog_set_website(m_pAboutDialog, sURL.isEmpty() ? nullptr : sURL.getStr());
+    }
+
+    virtual void set_website_label(const OUString& rLabel) override
+    {
+        OString sLabel(OUStringToOString(rLabel, RTL_TEXTENCODING_UTF8));
+        gtk_about_dialog_set_website_label(m_pAboutDialog, sLabel.isEmpty() ? nullptr : sLabel.getStr());
+    }
+
+    virtual OUString get_website_label() const override
+    {
+        const gchar* pText = gtk_about_dialog_get_website_label(m_pAboutDialog);
+        return OUString(pText, pText ? strlen(pText) : 0, RTL_TEXTENCODING_UTF8);
+    }
+
+    virtual void set_logo(VirtualDevice* pDevice) override
+    {
+        GdkPixbuf* pixbuf = pDevice ? getPixbuf(*pDevice) : nullptr;
+        if (!pixbuf)
+            gtk_about_dialog_set_logo(m_pAboutDialog, nullptr);
+        else
+        {
+            gtk_about_dialog_set_logo(m_pAboutDialog, pixbuf);
+            g_object_unref(pixbuf);
+        }
+    }
+
+    virtual void set_background(VirtualDevice* pDevice) override
+    {
+        GtkStyleContext *pStyleContext = gtk_widget_get_style_context(GTK_WIDGET(m_pAboutDialog));
+        if (m_pCssProvider)
+        {
+            gtk_style_context_remove_provider(pStyleContext, GTK_STYLE_PROVIDER(m_pCssProvider));
+            m_pCssProvider= nullptr;
+        }
+
+        mxBackgroundImage.reset();
+
+        if (pDevice)
+        {
+            mxBackgroundImage.reset(new utl::TempFile());
+            mxBackgroundImage->EnableKillingFile(true);
+
+            OString sOutput = mxBackgroundImage->GetFileName().toUtf8();
+
+            cairo_surface_t* orig_surface = get_underlying_cairo_surface(*pDevice);
+            double m_fXScale, m_fYScale;
+            dl_cairo_surface_get_device_scale(orig_surface, &m_fXScale, &m_fYScale);
+
+            cairo_surface_t* surface;
+            if (m_fXScale != 1.0 || m_fYScale != -1)
+            {
+                Size aSize(pDevice->GetOutputSizePixel());
+                surface = cairo_surface_create_similar_image(orig_surface,
+                                                             CAIRO_FORMAT_ARGB32,
+                                                             aSize.Width(),
+                                                             aSize.Height());
+                cairo_t* cr = cairo_create(surface);
+                cairo_set_source_surface(cr, orig_surface, 0, 0);
+                cairo_paint(cr);
+                cairo_destroy(cr);
+            }
+            else
+                surface = orig_surface;
+
+            cairo_surface_write_to_png(surface, sOutput.getStr());
+
+            if (surface != orig_surface)
+                cairo_surface_destroy(surface);
+
+            m_pCssProvider = gtk_css_provider_new();
+            OUString aBuffer = "* { background-image: url(\"" + mxBackgroundImage->GetURL() + "\"); }";
+            OString aResult = OUStringToOString(aBuffer, RTL_TEXTENCODING_UTF8);
+            gtk_css_provider_load_from_data(m_pCssProvider, aResult.getStr(), aResult.getLength(), nullptr);
+            gtk_style_context_add_provider(pStyleContext, GTK_STYLE_PROVIDER(m_pCssProvider),
+                                           GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+        }
+    }
+
+    virtual ~GtkInstanceAboutDialog() override
+    {
+        set_background(nullptr);
+    }
+};
+
 class GtkInstanceFrame : public GtkInstanceContainer, public virtual weld::Frame
 {
 private:
@@ -10057,6 +10202,24 @@ private:
                     set_primary_text(pMessageDialog, (*m_pStringReplace)(get_primary_text(pMessageDialog)));
                     set_secondary_text(pMessageDialog, (*m_pStringReplace)(get_secondary_text(pMessageDialog)));
                 }
+                else if (GTK_IS_ABOUT_DIALOG(pWindow))
+                {
+                    GtkAboutDialog* pAboutDialog = GTK_ABOUT_DIALOG(pWindow);
+                    const gchar *pComments = gtk_about_dialog_get_comments(pAboutDialog);
+                    if (pComments)
+                    {
+                        OUString sComments(pComments, strlen(pComments), RTL_TEXTENCODING_UTF8);
+                        sComments = (*m_pStringReplace)(sComments);
+                        gtk_about_dialog_set_comments(pAboutDialog, OUStringToOString(sComments, RTL_TEXTENCODING_UTF8).getStr());
+                    }
+                    const gchar *pProgramName = gtk_about_dialog_get_program_name(pAboutDialog);
+                    if (pProgramName)
+                    {
+                        OUString sProgramName(pProgramName, strlen(pProgramName), RTL_TEXTENCODING_UTF8);
+                        sProgramName = (*m_pStringReplace)(sProgramName);
+                        gtk_about_dialog_set_program_name(pAboutDialog, OUStringToOString(sProgramName, RTL_TEXTENCODING_UTF8).getStr());
+                    }
+                }
             }
         }
     }
@@ -10176,6 +10339,15 @@ public:
         return std::make_unique<GtkInstanceMessageDialog>(pMessageDialog, this, bTakeOwnership);
     }
 
+    virtual std::unique_ptr<weld::AboutDialog> weld_about_dialog(const OString &id, bool bTakeOwnership) override
+    {
+        GtkAboutDialog* pAboutDialog = GTK_ABOUT_DIALOG(gtk_builder_get_object(m_pBuilder, id.getStr()));
+        if (!pAboutDialog)
+            return nullptr;
+        gtk_window_set_transient_for(GTK_WINDOW(pAboutDialog), GTK_WINDOW(gtk_widget_get_toplevel(m_pParentWidget)));
+        return std::make_unique<GtkInstanceAboutDialog>(pAboutDialog, this, bTakeOwnership);
+    }
+
     virtual std::unique_ptr<weld::Dialog> weld_dialog(const OString &id, bool bTakeOwnership) override
     {
         GtkDialog* pDialog = GTK_DIALOG(gtk_builder_get_object(m_pBuilder, id.getStr()));


More information about the Libreoffice-commits mailing list