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/graphicfilter.hxx> 26 #include <vcl/settings.hxx> 27 #include <vcl/stdtext.hxx> 28 #include <vcl/svapp.hxx> 29 #include <vcl/virdev.hxx> 30 #include <vcl/weld.hxx> 31 32 #include <unotools/configmgr.hxx> 33 #include <unotools/bootstrap.hxx> 34 #include <com/sun/star/uno/Any.h> 35 #include <svtools/langhelp.hxx> 36 #include <i18nlangtag/languagetag.hxx> 37 38 #include <com/sun/star/system/SystemShellExecuteFlags.hpp> 39 #include <com/sun/star/system/SystemShellExecute.hpp> 40 #include <comphelper/processfactory.hxx> 41 #include <comphelper/anytostring.hxx> 42 #include <cppuhelper/exc_hlp.hxx> 43 #include <svtools/optionsdrawinglayer.hxx> 44 45 #include <about.hxx> 46 #include <dialmgr.hxx> 47 #include <strings.hrc> 48 #include <config_buildid.h> 49 #include <sfx2/app.hxx> 50 51 #if HAVE_FEATURE_OPENCL 52 #include <opencl/openclwrapper.hxx> 53 #endif 54 #include <officecfg/Office/Common.hxx> 55 #include <officecfg/Office/Calc.hxx> 56 57 using namespace ::com::sun::star::uno; 58 using namespace ::com::sun::star::beans; 59 using namespace ::com::sun::star; 60 61 AboutDialog::AboutDialog(weld::Window* pParent) 62 : m_xBuilder(Application::CreateBuilder(pParent, "cui/ui/aboutdialog.ui")) 63 , m_xDialog(m_xBuilder->weld_about_dialog("AboutDialog")) 64 , m_xContentArea(m_xDialog->weld_content_area()) 65 { 66 m_xDialog->add_button(GetStandardText(StandardButtonType::Close), RET_CLOSE); 67 m_xDialog->add_button(CuiResId(RID_SVXSTR_ABOUT_CREDITS), 101); 68 m_xDialog->add_button(CuiResId(RID_SVXSTR_ABOUT_WEBSITE), 102); 69 m_xDialog->add_button(CuiResId(RID_SVXSTR_ABOUT_RELEASE_NOTES), 103); 70 71 m_xCreditsButton.reset(m_xDialog->weld_widget_for_response(101)); 72 m_xCreditsButton->set_secondary(true); 73 m_xWebsiteButton.reset(m_xDialog->weld_widget_for_response(102)); 74 m_xWebsiteButton->set_secondary(true); 75 m_xReleaseNotesButton.reset(m_xDialog->weld_widget_for_response(103)); 76 m_xReleaseNotesButton->set_secondary(true); 77 m_xCloseButton.reset(m_xDialog->weld_widget_for_response(RET_CLOSE)); 78 79 m_buildIdLinkString = m_xDialog->get_website_label(); 80 81 m_xDialog->set_version(GetVersionString()); 82 m_xDialog->set_copyright(GetCopyrightString()); 83 84 SetBuildIdLink(); 85 86 SetLogo(); 87 88 m_xDialog->connect_size_allocate(LINK(this, AboutDialog, SizeAllocHdl)); 89 90 // Connect all handlers 91 m_xCreditsButton->connect_clicked( LINK( this, AboutDialog, HandleClick ) ); 92 m_xWebsiteButton->connect_clicked( LINK( this, AboutDialog, HandleClick ) ); 93 m_xReleaseNotesButton->connect_clicked( LINK( this, AboutDialog, HandleClick ) ); 94 m_xCloseButton->grab_focus(); 95 } 96 97 AboutDialog::~AboutDialog() 98 { 99 } 100 101 IMPL_LINK(AboutDialog, HandleClick, weld::Button&, rButton, void) 102 { 103 OUString sURL = ""; 104 105 // Find which button was pressed and from this, get the URL to be opened 106 if (&rButton == m_xCreditsButton.get()) 107 sURL = CuiResId(RID_SVXSTR_ABOUT_CREDITS_URL); 108 else if (&rButton == m_xWebsiteButton.get()) 109 { 110 sURL = officecfg::Office::Common::Help::StartCenter::InfoURL::get(); 111 localizeWebserviceURI(sURL); 112 } 113 else if (&rButton == m_xReleaseNotesButton.get()) 114 { 115 sURL = officecfg::Office::Common::Menus::ReleaseNotesURL::get() + 116 "?LOvers=" + utl::ConfigManager::getProductVersion() + 117 "&LOlocale=" + LanguageTag(utl::ConfigManager::getUILocale()).getLanguage(); 118 } 119 120 // If the URL is empty, don't do anything 121 if ( sURL.isEmpty() ) 122 return; 123 try 124 { 125 Reference< css::system::XSystemShellExecute > xSystemShellExecute( 126 css::system::SystemShellExecute::create(::comphelper::getProcessComponentContext() ) ); 127 xSystemShellExecute->execute( sURL, OUString(), css::system::SystemShellExecuteFlags::URIS_ONLY ); 128 } 129 catch (const Exception&) 130 { 131 Any exc( ::cppu::getCaughtException() ); 132 OUString msg( ::comphelper::anyToString( exc ) ); 133 const SolarMutexGuard guard; 134 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(getDialog(), 135 VclMessageType::Warning, VclButtonsType::Ok, msg)); 136 xErrorBox->set_title(m_xDialog->get_title()); 137 xErrorBox->run(); 138 } 139 } 140 141 void AboutDialog::SetBuildIdLink() 142 { 143 const OUString buildId = GetBuildId(); 144 145 if (IsStringValidGitHash(buildId)) 146 { 147 if (m_buildIdLinkString.indexOf("$GITHASH") == -1) 148 { 149 SAL_WARN( "cui.dialogs", "translated git hash string in translations doesn't contain $GITHASH placeholder" ); 150 m_buildIdLinkString += " $GITHASH"; 151 } 152 153 m_xDialog->set_website_label(m_buildIdLinkString.replaceAll("$GITHASH", buildId)); 154 m_xDialog->set_website("https://hub.libreoffice.org/git-core/" + buildId); 155 } 156 else 157 { 158 m_xDialog->set_website_label(OUString()); 159 m_xDialog->set_website(OUString()); 160 } 161 } 162 163 void AboutDialog::SetLogo() 164 { 165 auto nWidth = m_xContentArea->get_preferred_size().Width(); 166 167 // fdo#67401 set AntiAliasing for SVG logo 168 SvtOptionsDrawinglayer aDrawOpt; 169 bool bOldAntiAliasSetting = aDrawOpt.IsAntiAliasing(); 170 aDrawOpt.SetAntiAliasing(true); 171 172 // load svg logo, specify desired width, scale height isotropically 173 SfxApplication::loadBrandSvg("flat_logo", aLogoBitmap, nWidth); 174 175 aDrawOpt.SetAntiAliasing(bOldAntiAliasSetting); 176 177 if (!aLogoBitmap) 178 m_xDialog->set_logo(nullptr); 179 else 180 { 181 Graphic aGraphic(aLogoBitmap); 182 m_xDialog->set_logo(aGraphic.GetXGraphic()); 183 } 184 } 185 186 IMPL_LINK(AboutDialog, SizeAllocHdl, const Size&, rSize, void) 187 { 188 if (rSize.Width() == aBackgroundBitmap.GetSizePixel().Width()) 189 return; 190 // Load background image 191 if (!(Application::GetSettings().GetStyleSettings().GetHighContrastMode())) 192 { 193 SfxApplication::loadBrandSvg("shell/about", aBackgroundBitmap, rSize.Width()); 194 Graphic aGraphic(aBackgroundBitmap); 195 m_xDialog->set_background(aGraphic.GetXGraphic()); 196 } 197 } 198 199 OUString AboutDialog::GetBuildId() 200 { 201 OUString sDefault; 202 OUString sBuildId(utl::Bootstrap::getBuildVersion(sDefault)); 203 if (!sBuildId.isEmpty()) 204 return sBuildId; 205 206 sBuildId = utl::Bootstrap::getBuildIdData(sDefault); 207 208 if (!sBuildId.isEmpty()) 209 { 210 return sBuildId.getToken( 0, '-' ); 211 } 212 213 OSL_ENSURE( !sBuildId.isEmpty(), "No BUILDID in bootstrap file" ); 214 return sBuildId; 215 } 216 217 OUString AboutDialog::GetLocaleString() 218 { 219 OUString aLocaleStr; 220 rtl_Locale * pLocale; 221 222 osl_getProcessLocale( &pLocale ); 223 224 if ( pLocale && pLocale->Language ) 225 { 226 if (pLocale->Country && rtl_uString_getLength( pLocale->Country) > 0) 227 aLocaleStr = OUString(pLocale->Language) + "_" + OUString(pLocale->Country); 228 else 229 aLocaleStr = OUString(pLocale->Language); 230 if (pLocale->Variant && rtl_uString_getLength( pLocale->Variant) > 0) 231 aLocaleStr += OUString(pLocale->Variant); 232 } 233 234 return aLocaleStr; 235 } 236 237 bool AboutDialog::IsStringValidGitHash(const OUString& hash) 238 { 239 for (int i = 0; i < hash.getLength(); i++) 240 { 241 if (!rtl::isAsciiHexDigit(hash[i])) 242 { 243 return false; 244 } 245 } 246 247 return true; 248 } 249 250 OUString AboutDialog::GetVersionString() 251 { 252 OUString sVersion = CuiResId(RID_SVXSTR_ABOUT_VERSION); 253 254 #ifdef _WIN64 255 sVersion += " (x64)"; 256 #elif defined(_WIN32) 257 sVersion += " (x86)"; 258 #endif 259 260 OUString sBuildId = GetBuildId(); 261 262 OUString aLocaleStr = Application::GetSettings().GetLanguageTag().getBcp47() + " (" + GetLocaleString() + ")"; 263 OUString aUILocaleStr = Application::GetSettings().GetUILanguageTag().getBcp47(); 264 265 if (!sBuildId.trim().isEmpty()) 266 { 267 sVersion += "\n"; 268 OUString sBuildStr = CuiResId(RID_SVXSTR_ABOUT_BUILDID); 269 if (sBuildStr.indexOf("$BUILDID") == -1) 270 { 271 SAL_WARN( "cui.dialogs", "translated Build Id string in translations doesn't contain $BUILDID placeholder" ); 272 sBuildStr += " $BUILDID"; 273 } 274 sVersion += sBuildStr.replaceAll("$BUILDID", sBuildId); 275 } 276 277 sVersion += "\n" + Application::GetHWOSConfInfo(); 278 279 bool const extra = EXTRA_BUILDID[0] != '\0'; 280 // extracted from the 'if' to avoid Clang -Wunreachable-code 281 if (extra) 282 { 283 sVersion += "\n" EXTRA_BUILDID; 284 } 285 286 OUString sLocaleStr(CuiResId(RID_SVXSTR_ABOUT_LOCALE)); 287 if (sLocaleStr.indexOf("$LOCALE") == -1) 288 { 289 SAL_WARN( "cui.dialogs", "translated locale string in translations doesn't contain $LOCALE placeholder" ); 290 sLocaleStr += " $LOCALE"; 291 } 292 sVersion += "\n" + sLocaleStr.replaceAll("$LOCALE", aLocaleStr); 293 294 OUString sUILocaleStr(CuiResId(RID_SVXSTR_ABOUT_UILOCALE)); 295 if (sUILocaleStr.indexOf("$LOCALE") == -1) 296 { 297 SAL_WARN( "cui.dialogs", "translated uilocale string in translations doesn't contain $LOCALE placeholder" ); 298 sUILocaleStr += " $LOCALE"; 299 } 300 sVersion += "; " + sUILocaleStr.replaceAll("$LOCALE", aUILocaleStr); 301 302 OUString aCalcMode = "Calc: "; // Calc calculation mode 303 304 #if HAVE_FEATURE_OPENCL 305 bool bOpenCL = openclwrapper::GPUEnv::isOpenCLEnabled(); 306 if (bOpenCL) 307 aCalcMode += "CL"; 308 #else 309 const bool bOpenCL = false; 310 #endif 311 312 static const bool bThreadingProhibited = std::getenv("SC_NO_THREADED_CALCULATION"); 313 bool bThreadedCalc = officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get(); 314 315 if (!bThreadingProhibited && !bOpenCL && bThreadedCalc) 316 { 317 if (!aCalcMode.endsWith(" ")) 318 aCalcMode += " "; 319 aCalcMode += "threaded"; 320 } 321 322 sVersion += "\n" + aCalcMode; 323 324 return sVersion; 325 } 326 327 OUString AboutDialog::GetCopyrightString() 328 { 329 OUString sVendorTextStr(CuiResId(RID_SVXSTR_ABOUT_VENDOR)); 330 OUString aCopyrightString = sVendorTextStr + "\n" 331 + CuiResId(RID_SVXSTR_ABOUT_COPYRIGHT) + "\n"; 332 333 if (utl::ConfigManager::getProductName() == "LibreOffice") 334 aCopyrightString += CuiResId(RID_SVXSTR_ABOUT_BASED_ON); 335 else 336 aCopyrightString += CuiResId(RID_SVXSTR_ABOUT_DERIVED); 337 338 return aCopyrightString; 339 } 340 341 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 342
