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
