xref: /core/cui/source/dialogs/about.cxx (revision dfc5acab)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <config_features.h>
21 #include <osl/process.h>
22 #include <sal/log.hxx>
23 #include <osl/diagnose.h>
24 #include <rtl/character.hxx>
25 #include <vcl/layout.hxx>
26 #include <vcl/weld.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/settings.hxx>
29 
30 #include <tools/stream.hxx>
31 #include <rtl/bootstrap.hxx>
32 #include <unotools/configmgr.hxx>
33 #include <unotools/bootstrap.hxx>
34 #include <com/sun/star/uno/Any.h>
35 #include <vcl/graph.hxx>
36 #include <vcl/graphicfilter.hxx>
37 #include <svtools/langhelp.hxx>
38 #include <i18nlangtag/languagetag.hxx>
39 
40 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
41 #include <com/sun/star/system/SystemShellExecute.hpp>
42 #include <comphelper/processfactory.hxx>
43 #include <comphelper/anytostring.hxx>
44 #include <cppuhelper/exc_hlp.hxx>
45 #include <cppuhelper/bootstrap.hxx>
46 #include <basegfx/numeric/ftools.hxx>
47 #include <com/sun/star/geometry/RealRectangle2D.hpp>
48 #include <svtools/optionsdrawinglayer.hxx>
49 
50 #include <sfx2/sfxuno.hxx>
51 #include <about.hxx>
52 #include <config_buildid.h>
53 #include <sfx2/app.hxx>
54 #include <rtl/ustrbuf.hxx>
55 #include <vcl/bitmap.hxx>
56 
57 #if HAVE_FEATURE_OPENCL
58 #include <opencl/openclwrapper.hxx>
59 #endif
60 #include <officecfg/Office/Common.hxx>
61 #include <officecfg/Office/Calc.hxx>
62 
63 using namespace ::com::sun::star::uno;
64 using namespace ::com::sun::star::beans;
65 using namespace ::com::sun::star;
66 
67 AboutDialog::AboutDialog(vcl::Window* pParent)
68     : SfxModalDialog(pParent, "AboutDialog", "cui/ui/aboutdialog.ui")
69 {
70     get(m_pLogoReplacement, "logoreplacement");
71     get(m_pLogoImage, "logo");
72     get(m_pVersion, "version");
73     get(m_pDescriptionText, "description");
74     get(m_pCopyrightText, "copyright");
75     get(m_pBuildIdLink, "buildIdLink");
76     m_aCopyrightTextStr = m_pCopyrightText->GetText();
77     get(m_pWebsiteButton, "website");
78     get(m_pCreditsButton, "credits");
79     m_aCreditsLinkStr = get<FixedText>("link")->GetText();
80     m_sBuildStr = get<FixedText>("buildid")->GetText();
81     m_aVendorTextStr = get<FixedText>("vendor")->GetText();
82     m_aVersionTextStr = m_pVersion->GetText();
83     m_aBasedTextStr = get<FixedText>("libreoffice")->GetText();
84     m_aBasedDerivedTextStr = get<FixedText>("derived")->GetText();
85     m_aLocaleStr = get<FixedText>("locale")->GetText();
86     m_aUILocaleStr = get<FixedText>("uilocale")->GetText();
87     m_buildIdLinkString = m_pBuildIdLink->GetText();
88 
89     m_pVersion->SetText(GetVersionString());
90 
91     OUString aCopyrightString = GetCopyrightString();
92     m_pCopyrightText->SetText( aCopyrightString );
93 
94     SetBuildIdLink();
95 
96     StyleControls();
97 
98     SetLogo();
99 
100     // Connect all handlers
101     m_pCreditsButton->SetClickHdl( LINK( this, AboutDialog, HandleClick ) );
102     m_pWebsiteButton->SetClickHdl( LINK( this, AboutDialog, HandleClick ) );
103 
104     get<PushButton>("close")->GrabFocus();
105 }
106 
107 AboutDialog::~AboutDialog()
108 {
109     disposeOnce();
110 }
111 
112 void AboutDialog::dispose()
113 {
114     m_pVersion.clear();
115     m_pDescriptionText.clear();
116     m_pCopyrightText.clear();
117     m_pLogoImage.clear();
118     m_pLogoReplacement.clear();
119     m_pCreditsButton.clear();
120     m_pWebsiteButton.clear();
121     m_pBuildIdLink.clear();
122     SfxModalDialog::dispose();
123 }
124 
125 IMPL_LINK( AboutDialog, HandleClick, Button*, pButton, void )
126 {
127     OUString sURL = "";
128 
129     // Find which button was pressed and from this, get the URL to be opened
130     if (pButton == m_pCreditsButton)
131         sURL = m_aCreditsLinkStr;
132     else if (pButton == m_pWebsiteButton)
133     {
134         sURL = officecfg::Office::Common::Help::StartCenter::InfoURL::get();
135         localizeWebserviceURI(sURL);
136     }
137 
138     // If the URL is empty, don't do anything
139     if ( sURL.isEmpty() )
140         return;
141     try
142     {
143         Reference< css::system::XSystemShellExecute > xSystemShellExecute(
144             css::system::SystemShellExecute::create(::comphelper::getProcessComponentContext() ) );
145         xSystemShellExecute->execute( sURL, OUString(), css::system::SystemShellExecuteFlags::URIS_ONLY );
146     }
147     catch (const Exception&)
148     {
149         Any exc( ::cppu::getCaughtException() );
150         OUString msg( ::comphelper::anyToString( exc ) );
151         const SolarMutexGuard guard;
152         std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(pButton->GetFrameWeld(),
153                                                        VclMessageType::Warning, VclButtonsType::Ok, msg));
154         xErrorBox->set_title(GetText());
155         xErrorBox->run();
156     }
157 }
158 
159 void AboutDialog::SetBuildIdLink()
160 {
161     const OUString buildId = GetBuildId();
162 
163     if (IsStringValidGitHash(buildId))
164     {
165         if (m_buildIdLinkString.indexOf("$GITHASH") == -1)
166         {
167             SAL_WARN( "cui.dialogs", "translated git hash string in translations doesn't contain $GITHASH placeholder" );
168             m_buildIdLinkString += " $GITHASH";
169         }
170 
171         m_pBuildIdLink->SetText(m_buildIdLinkString.replaceAll("$GITHASH", buildId));
172         m_pBuildIdLink->SetURL("https://hub.libreoffice.org/git-core/" + buildId);
173     }
174     else
175     {
176         m_pBuildIdLink->Hide();
177     }
178 }
179 
180 void AboutDialog::StyleControls()
181 {
182     // Make all the controls have a transparent background
183     m_pLogoImage->SetBackground();
184     m_pLogoReplacement->SetPaintTransparent(true);
185     m_pVersion->SetPaintTransparent(true);
186     m_pDescriptionText->SetPaintTransparent(true);
187     m_pCopyrightText->SetPaintTransparent(true);
188 
189     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
190 
191     const vcl::Font& aLabelFont = rStyleSettings.GetLabelFont();
192     vcl::Font aLargeFont = aLabelFont;
193     aLargeFont.SetFontSize(Size( 0, aLabelFont.GetFontSize().Height() * 3));
194 
195     // Logo Replacement Text
196     m_pLogoReplacement->SetControlFont(aLargeFont);
197 
198     // Description Text
199     aLargeFont.SetFontSize(Size(0, aLabelFont.GetFontSize().Height() * 1.3));
200     m_pDescriptionText->SetControlFont(aLargeFont);
201 }
202 
203 void AboutDialog::SetLogo()
204 {
205     long nWidth = get_content_area()->get_preferred_size().Width();
206 
207     // fdo#67401 set AntiAliasing for SVG logo
208     SvtOptionsDrawinglayer aDrawOpt;
209     bool bOldAntiAliasSetting = aDrawOpt.IsAntiAliasing();
210     aDrawOpt.SetAntiAliasing(true);
211 
212     // load svg logo, specify desired width, scale height isotropically
213     if (SfxApplication::loadBrandSvg("flat_logo", aLogoBitmap, nWidth) &&
214         !aLogoBitmap.IsEmpty())
215     {
216         m_pLogoImage->SetImage(Image(aLogoBitmap));
217         m_pLogoReplacement->Hide();
218         m_pLogoImage->Show();
219     }
220     else
221     {
222         m_pLogoImage->Hide();
223         m_pLogoReplacement->Show();
224     }
225     aDrawOpt.SetAntiAliasing(bOldAntiAliasSetting);
226 }
227 
228 void AboutDialog::Resize()
229 {
230     SfxModalDialog::Resize();
231 
232     // Load background image
233     if (isInitialLayout(this) && !(Application::GetSettings().GetStyleSettings().GetHighContrastMode()))
234     {
235         SfxApplication::loadBrandSvg("shell/about", aBackgroundBitmap, GetSizePixel().Width());
236     }
237 }
238 
239 void AboutDialog::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect)
240 {
241     rRenderContext.SetClipRegion(vcl::Region(rRect));
242 
243     Size aSize(GetOutputSizePixel());
244     Point aPos(aSize.Width() - aBackgroundBitmap.GetSizePixel().Width(),
245                aSize.Height() - aBackgroundBitmap.GetSizePixel().Height());
246 
247     rRenderContext.DrawBitmapEx(aPos, aBackgroundBitmap);
248 }
249 
250 OUString AboutDialog::GetBuildId()
251 {
252     OUString sDefault;
253     OUString sBuildId(utl::Bootstrap::getBuildVersion(sDefault));
254     if (!sBuildId.isEmpty())
255         return sBuildId;
256 
257     sBuildId = utl::Bootstrap::getBuildIdData(sDefault);
258 
259     if (!sBuildId.isEmpty())
260     {
261         return sBuildId.getToken( 0, '-' );
262     }
263 
264     OSL_ENSURE( !sBuildId.isEmpty(), "No BUILDID in bootstrap file" );
265     return sBuildId;
266 }
267 
268 OUString AboutDialog::GetLocaleString()
269 {
270     OUString aLocaleStr;
271     rtl_Locale * pLocale;
272 
273     osl_getProcessLocale( &pLocale );
274 
275     if ( pLocale && pLocale->Language )
276     {
277         if (pLocale->Country && rtl_uString_getLength( pLocale->Country) > 0)
278             aLocaleStr = OUString(pLocale->Language) + "_" + OUString(pLocale->Country);
279         else
280             aLocaleStr = OUString(pLocale->Language);
281         if (pLocale->Variant && rtl_uString_getLength( pLocale->Variant) > 0)
282             aLocaleStr += OUString(pLocale->Variant);
283     }
284 
285     return aLocaleStr;
286 }
287 
288 bool AboutDialog::IsStringValidGitHash(const OUString& hash)
289 {
290     for (int i = 0; i < hash.getLength(); i++)
291     {
292         if (!rtl::isAsciiHexDigit(hash[i]))
293         {
294             return false;
295         }
296     }
297 
298     return true;
299 }
300 
301 OUString AboutDialog::GetVersionString()
302 {
303     OUString sVersion = m_aVersionTextStr;
304 
305 #ifdef _WIN64
306     sVersion += " (x64)";
307 #endif
308 
309     OUString sBuildId = GetBuildId();
310 
311     OUString aLocaleStr = Application::GetSettings().GetLanguageTag().getBcp47() + " (" + GetLocaleString() + ")";
312     OUString aUILocaleStr = Application::GetSettings().GetUILanguageTag().getBcp47();
313 
314     if (!sBuildId.trim().isEmpty())
315     {
316         sVersion += "\n";
317         if (m_sBuildStr.indexOf("$BUILDID") == -1)
318         {
319             SAL_WARN( "cui.dialogs", "translated Build Id string in translations doesn't contain $BUILDID placeholder" );
320             m_sBuildStr += " $BUILDID";
321         }
322         sVersion += m_sBuildStr.replaceAll("$BUILDID", sBuildId);
323     }
324 
325     sVersion += "\n" + Application::GetHWOSConfInfo();
326 
327     bool const extra = EXTRA_BUILDID[0] != '\0';
328         // extracted from the 'if' to avoid Clang -Wunreachable-code
329     if (extra)
330     {
331         sVersion += "\n" EXTRA_BUILDID;
332     }
333 
334     if (m_aLocaleStr.indexOf("$LOCALE") == -1)
335     {
336         SAL_WARN( "cui.dialogs", "translated locale string in translations doesn't contain $LOCALE placeholder" );
337         m_aLocaleStr += " $LOCALE";
338     }
339     sVersion += "\n" + m_aLocaleStr.replaceAll("$LOCALE", aLocaleStr);
340 
341     if (m_aUILocaleStr.indexOf("$LOCALE") == -1)
342     {
343         SAL_WARN( "cui.dialogs", "translated uilocale string in translations doesn't contain $LOCALE placeholder" );
344         m_aUILocaleStr += " $LOCALE";
345     }
346     sVersion += "; " + m_aUILocaleStr.replaceAll("$LOCALE", aUILocaleStr);
347 
348     OUString aCalcMode = "Calc: "; // Calc calculation mode
349 
350 #if HAVE_FEATURE_OPENCL
351     bool bOpenCL = openclwrapper::GPUEnv::isOpenCLEnabled();
352     if (bOpenCL)
353         aCalcMode += "CL";
354 #else
355     const bool bOpenCL = false;
356 #endif
357 
358     static const bool bThreadingProhibited = std::getenv("SC_NO_THREADED_CALCULATION");
359     bool bThreadedCalc = officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get();
360 
361     if (!bThreadingProhibited && !bOpenCL && bThreadedCalc)
362     {
363         if (!aCalcMode.endsWith(" "))
364             aCalcMode += " ";
365         aCalcMode += "threaded";
366     }
367 
368     sVersion += "\n" + aCalcMode;
369 
370     return sVersion;
371 }
372 
373 OUString AboutDialog::GetCopyrightString()
374 {
375     OUString aCopyrightString  = m_aVendorTextStr + "\n"
376                                + m_aCopyrightTextStr + "\n";
377 
378     if (utl::ConfigManager::getProductName() == "LibreOffice")
379         aCopyrightString += m_aBasedTextStr;
380     else
381         aCopyrightString += m_aBasedDerivedTextStr;
382 
383     return aCopyrightString;
384 }
385 
386 bool AboutDialog::Close()
387 {
388     EndDialog( RET_OK );
389     return false;
390 }
391 
392 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
393