xref: /core/cui/source/dialogs/about.cxx (revision cae3854f05b3e2ca65b56e8b05183d6817f9bdf5)
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 <sal/config.h>
21 
22 #include <cassert>
23 
24 #include <about.hxx>
25 
26 #include <osl/process.h>     //osl_getProcessLocale
27 #include <rtl/bootstrap.hxx>
28 #include <sal/log.hxx>       //SAL_WARN
29 #include <vcl/graph.hxx>     //Graphic
30 #include <vcl/settings.hxx>  //GetSettings
31 #include <vcl/svapp.hxx>     //Application::
32 #include <vcl/weld.hxx>
33 #include <unotools/resmgr.hxx> //Translate
34 
35 #include <config_buildid.h> //EXTRA_BUILDID
36 #include <config_features.h>
37 #include <dialmgr.hxx>      //CuiResId
38 #include <i18nlangtag/languagetag.hxx>
39 #include <sfx2/app.hxx> //SfxApplication::loadBrandSvg
40 #include <strings.hrc>
41 #include <svtools/langhelp.hxx>
42 #include <unotools/bootstrap.hxx> //utl::Bootstrap::getBuildIdData
43 #include <unotools/configmgr.hxx> //ConfigManager::
44 
45 #include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
46 #include <vcl/unohelp2.hxx>
47 
48 #include <config_feature_opencl.h>
49 #if HAVE_FEATURE_OPENCL
50 #include <opencl/openclwrapper.hxx>
51 #endif
52 #include <officecfg/Office/Calc.hxx>
53 #include <officecfg/Office/Common.hxx>
54 
55 using namespace ::com::sun::star::uno;
56 
AboutDialog(weld::Window * pParent)57 AboutDialog::AboutDialog(weld::Window *pParent)
58     : GenericDialogController(pParent, u"cui/ui/aboutdialog.ui"_ustr, u"AboutDialog"_ustr),
59       m_pCreditsButton(m_xBuilder->weld_link_button(u"btnCredits"_ustr)),
60       m_pWebsiteButton(m_xBuilder->weld_link_button(u"btnWebsite"_ustr)),
61       m_pReleaseNotesButton(m_xBuilder->weld_link_button(u"btnReleaseNotes"_ustr)),
62       m_pCloseButton(m_xBuilder->weld_button(u"btnClose"_ustr)),
63       m_pCopyButton(m_xBuilder->weld_button(u"btnCopyVersion"_ustr)),
64       m_pBrandImage(m_xBuilder->weld_image(u"imBrand"_ustr)),
65       m_pAboutImage(m_xBuilder->weld_image(u"imAbout"_ustr)),
66       m_pVersionLabel(m_xBuilder->weld_label(u"lbVersionString"_ustr)),
67       m_pBuildCaption(m_xBuilder->weld_label(u"lbBuild"_ustr)),
68       m_pBuildLabel(m_xBuilder->weld_link_button(u"lbBuildString"_ustr)),
69       m_pEnvLabel(m_xBuilder->weld_label(u"lbEnvString"_ustr)),
70       m_pUILabel(m_xBuilder->weld_label(u"lbUIString"_ustr)),
71       m_pLocaleLabel(m_xBuilder->weld_label(u"lbLocaleString"_ustr)),
72       m_pMiscLabel(m_xBuilder->weld_label(u"lbMiscString"_ustr)),
73       m_pCopyrightLabel(m_xBuilder->weld_label(u"lbCopyright"_ustr)) {
74 
75   // Labels
76   m_pVersionLabel->set_label(GetVersionString());
77 
78   OUString sbuildId = GetBuildString();
79   if (IsStringValidGitHash(sbuildId)) {
80     const tools::Long nMaxChar = 25;
81     m_pBuildLabel->set_uri("https://gerrit.libreoffice.org/gitweb?p=core.git;a=log;h="
82                            + sbuildId);
83     m_pBuildLabel->set_label(sbuildId.getLength() > nMaxChar ? sbuildId.replaceAt(
84                                  nMaxChar, sbuildId.getLength() - nMaxChar, u"...")
85                                                              : sbuildId);
86   } else {
87     m_pBuildCaption->hide();
88     m_pBuildLabel->hide();
89   }
90 
91   m_pEnvLabel->set_label(Application::GetHWOSConfInfo(1));
92   m_pUILabel->set_label(Application::GetHWOSConfInfo(2));
93   m_pLocaleLabel->set_label(GetLocaleString());
94   m_pMiscLabel->set_label(GetMiscString());
95   m_pCopyrightLabel->set_label(GetCopyrightString());
96 
97   // Images
98   const tools::Long nWidth(m_pCopyrightLabel->get_preferred_size().getWidth());
99   Bitmap aBackgroundBitmap;
100 
101   if (SfxApplication::loadBrandSvg(Application::GetSettings()
102                                            .GetStyleSettings()
103                                            .GetDialogColor()
104                                            .IsDark()
105                                        ? "shell/logo_inverted"
106                                        : "shell/logo",
107                                    aBackgroundBitmap, nWidth * 0.8)) {
108     // Eliminate white background when Skia is disabled by not drawing the
109     // background bitmap to a VirtualDevice. On most platforms, non-Skia
110     // VirtualDevices will be filled with a solid color when drawing
111     // the bitmap.
112     Graphic aGraphic(aBackgroundBitmap);
113     m_pBrandImage->set_image(aGraphic.GetXGraphic());
114   }
115   if (SfxApplication::loadBrandSvg("shell/about", aBackgroundBitmap, nWidth * 0.9)) {
116     // Eliminate white background when Skia is disabled by not drawing the
117     // background bitmap to a VirtualDevice. On most platforms, non-Skia
118     // VirtualDevices will be filled with a solid color when drawing
119     // the bitmap.
120     Graphic aGraphic(aBackgroundBitmap);
121     m_pAboutImage->set_image(aGraphic.GetXGraphic());
122   }
123 
124   // Links
125   m_pCreditsButton->set_uri(officecfg::Office::Common::Menus::CreditsURL::get());
126 
127   OUString sURL(officecfg::Office::Common::Help::StartCenter::InfoURL::get());
128   localizeWebserviceURI(sURL);
129   m_pWebsiteButton->set_uri(sURL);
130 
131   // See also SID_WHATSNEW in sfx2/source/appl/appserv.cxx
132   sURL = officecfg::Office::Common::Menus::ReleaseNotesURL::get() +
133          "?LOvers=" + utl::ConfigManager::getProductVersion() + "&LOlocale=" +
134          LanguageTag(utl::ConfigManager::getUILocale()).getBcp47();
135   m_pReleaseNotesButton->set_uri(sURL);
136 
137   // Handler
138   m_pCopyButton->connect_clicked(LINK(this, AboutDialog, HandleClick));
139   m_pCloseButton->grab_focus();
140 }
141 
~AboutDialog()142 AboutDialog::~AboutDialog() {}
143 
IsStringValidGitHash(std::u16string_view hash)144 bool AboutDialog::IsStringValidGitHash(std::u16string_view hash) {
145   return std::all_of(hash.begin(), hash.end(),
146                      [](auto &rSymbol) { return std::isxdigit(rSymbol); });
147 }
148 
GetVersionString()149 OUString AboutDialog::GetVersionString() {
150   OUString arch;
151   auto const ok = rtl::Bootstrap::get(u"_ARCH"_ustr, arch);
152   assert(ok); (void) ok;
153   OUString sVersion = CuiResId(TranslateId(nullptr, "%ABOUTBOXPRODUCTVERSION%ABOUTBOXPRODUCTVERSIONSUFFIX")) + " (" + arch + ")";
154 
155 #if HAVE_FEATURE_COMMUNITY_FLAVOR
156   sVersion += " / LibreOffice Community";
157 #endif
158 
159   return sVersion;
160 }
161 
GetBuildString()162 OUString AboutDialog::GetBuildString()
163 {
164   OUString sBuildId(utl::Bootstrap::getBuildIdData(u""_ustr));
165   SAL_WARN_IF(sBuildId.isEmpty(), "cui.dialogs", "No BUILDID in bootstrap file");
166 
167   return sBuildId;
168 }
169 
GetLocaleString(const bool bLocalized)170 OUString AboutDialog::GetLocaleString(const bool bLocalized) {
171 
172   OUString sLocaleStr;
173 
174   rtl_Locale *pLocale;
175   osl_getProcessLocale(&pLocale);
176   if (pLocale && pLocale->Language) {
177     if (pLocale->Country && rtl_uString_getLength(pLocale->Country) > 0)
178       sLocaleStr = OUString::unacquired(&pLocale->Language) + "_" +
179                    OUString::unacquired(&pLocale->Country);
180     else
181       sLocaleStr = OUString(pLocale->Language);
182     if (pLocale->Variant && rtl_uString_getLength(pLocale->Variant) > 0)
183       sLocaleStr += OUString(pLocale->Variant);
184   }
185 
186   sLocaleStr = Application::GetSettings().GetLanguageTag().getBcp47() + " (" +
187                sLocaleStr + ")";
188 
189   OUString aUILocaleStr =
190       Application::GetSettings().GetUILanguageTag().getBcp47();
191   OUString sUILocaleStr;
192   if (bLocalized)
193      sUILocaleStr = CuiResId(RID_CUISTR_ABOUT_UILOCALE);
194   else
195      sUILocaleStr = Translate::get(RID_CUISTR_ABOUT_UILOCALE, Translate::Create("cui", LanguageTag(u"en-US"_ustr)));
196 
197   if (sUILocaleStr.indexOf("$LOCALE") == -1) {
198     SAL_WARN("cui.dialogs", "translated uilocale string in translations "
199                             "doesn't contain $LOCALE placeholder");
200     sUILocaleStr += " $LOCALE";
201   }
202   sUILocaleStr = sUILocaleStr.replaceAll("$LOCALE", aUILocaleStr);
203 
204   return sLocaleStr + "; " + sUILocaleStr;
205 }
206 
GetMiscString()207 OUString AboutDialog::GetMiscString() {
208 
209   OUString sMisc;
210 
211   bool const extra = EXTRA_BUILDID[0] != '\0';
212   // extracted from the 'if' to avoid Clang -Wunreachable-code
213   if (extra) {
214     sMisc = EXTRA_BUILDID "\n";
215   }
216 
217   OUString aCalcMode; // Calc calculation mode
218 
219 #if HAVE_FEATURE_OPENCL
220   if (openclwrapper::GPUEnv::isOpenCLEnabled())
221     aCalcMode += " CL";
222 #endif
223 
224   static const bool bThreadingProhibited =
225       std::getenv("SC_NO_THREADED_CALCULATION");
226   bool bThreadedCalc = officecfg::Office::Calc::Formula::Calculation::
227       UseThreadedCalculationForFormulaGroups::get();
228 
229   if (!bThreadingProhibited && bThreadedCalc) {
230     aCalcMode += " threaded";
231   }
232 
233   if (officecfg::Office::Calc::Defaults::Sheet::JumboSheets::get())
234   {
235     aCalcMode += " Jumbo";
236   }
237 
238   if (aCalcMode.isEmpty())
239       aCalcMode = " default";
240   sMisc += "Calc:" + aCalcMode;
241 
242   return sMisc;
243 }
244 
GetCopyrightString()245 OUString AboutDialog::GetCopyrightString() {
246   OUString sVendorTextStr(CuiResId(RID_CUISTR_ABOUT_VENDOR));
247   OUString aCopyrightString =
248       sVendorTextStr + "\n" + CuiResId(RID_CUISTR_ABOUT_COPYRIGHT) + "\n";
249 
250   if (utl::ConfigManager::getProductName() == "LibreOffice")
251     aCopyrightString += CuiResId(RID_CUISTR_ABOUT_BASED_ON);
252   else
253     aCopyrightString += CuiResId(RID_CUISTR_ABOUT_DERIVED);
254 
255   return aCopyrightString;
256 }
257 
258 // special labels to comply with previous version info
259 // untranslated English for QA
IMPL_LINK_NOARG(AboutDialog,HandleClick,weld::Button &,void)260 IMPL_LINK_NOARG(AboutDialog, HandleClick, weld::Button &, void) {
261   css::uno::Reference<css::datatransfer::clipboard::XClipboard> xClipboard =
262       css::datatransfer::clipboard::SystemClipboard::create(
263           comphelper::getProcessComponentContext());
264 
265   OUString sInfo = "Version: " + m_pVersionLabel->get_label() + "\n" // version
266                    "Build ID: " + GetBuildString() + "\n" + // build id
267                    Application::GetHWOSConfInfo(0,false) + "\n" // env+UI
268                    "Locale: " + GetLocaleString(false) + "\n" + // locale
269                    GetMiscString(); // misc
270 
271   vcl::unohelper::TextDataObject::CopyStringTo(sInfo, xClipboard);
272 }
273 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
274