diff options
author | Caolán McNamara <caolanm@redhat.com> | 2019-06-04 11:34:28 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2019-06-06 09:57:53 +0200 |
commit | a30a5d1b8af18d19526f1980df41857f455cc8ef (patch) | |
tree | e8add75abca3c336cbc46936a7d19028ba4251aa | |
parent | 7665246ac8addc002f74e3a9b22d1baeda448af3 (diff) |
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@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r-- | cui/inc/strings.hrc | 13 | ||||
-rw-r--r-- | cui/source/dialogs/about.cxx | 215 | ||||
-rw-r--r-- | cui/source/factory/dlgfact.cxx | 10 | ||||
-rw-r--r-- | cui/source/factory/dlgfact.hxx | 2 | ||||
-rw-r--r-- | cui/source/inc/about.hxx | 59 | ||||
-rw-r--r-- | cui/uiconfig/ui/aboutdialog.ui | 328 | ||||
-rw-r--r-- | include/sfx2/sfxdlg.hxx | 1 | ||||
-rw-r--r-- | include/vcl/aboutdialog.hxx | 60 | ||||
-rw-r--r-- | include/vcl/dialog.hxx | 2 | ||||
-rw-r--r-- | include/vcl/weld.hxx | 17 | ||||
-rw-r--r-- | sfx2/source/appl/appserv.cxx | 2 | ||||
-rw-r--r-- | solenv/sanitizers/ui/cui.suppr | 12 | ||||
-rw-r--r-- | solenv/sanitizers/ui/vcl.suppr | 12 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/UIConfig_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/source/app/salvtables.cxx | 79 | ||||
-rw-r--r-- | vcl/source/window/aboutdialog.cxx | 159 | ||||
-rw-r--r-- | vcl/source/window/builder.cxx | 8 | ||||
-rw-r--r-- | vcl/uiconfig/ui/aboutbox.ui | 135 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 173 |
20 files changed, 779 insertions, 510 deletions
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..c7459a81a1f4 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,118 @@ 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) + { + } + + 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 +10197,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 +10334,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())); |