Line data Source code
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 <vcl/svapp.hxx>
21 : #include <vcl/msgbox.hxx>
22 :
23 : #include <tools/stream.hxx>
24 : #include <rtl/bootstrap.hxx>
25 : #include <unotools/configmgr.hxx>
26 : #include <unotools/bootstrap.hxx>
27 : #include <com/sun/star/uno/Any.h>
28 : #include <vcl/graph.hxx>
29 : #include <svtools/filter.hxx>
30 : #include <svtools/langhelp.hxx>
31 :
32 : #include "com/sun/star/system/SystemShellExecuteFlags.hpp"
33 : #include "com/sun/star/system/SystemShellExecute.hpp"
34 : #include <comphelper/processfactory.hxx>
35 : #include "comphelper/anytostring.hxx"
36 : #include "cppuhelper/exc_hlp.hxx"
37 : #include "cppuhelper/bootstrap.hxx"
38 :
39 : #include <sfx2/sfxuno.hxx>
40 : #include <sfx2/sfxcommands.h>
41 : #include "about.hxx"
42 : #include "about.hrc"
43 : #include <sfx2/sfxdefs.hxx>
44 : #include <sfx2/app.hxx>
45 : #include <rtl/ustrbuf.hxx>
46 : #include <vcl/bitmap.hxx>
47 : #include <officecfg/Office/Common.hxx>
48 :
49 : using namespace ::com::sun::star::uno;
50 : using namespace ::com::sun::star::beans;
51 : using namespace ::com::sun::star;
52 :
53 : enum AboutDialogButton
54 : {
55 : CREDITS_BUTTON,
56 : WEBSITE_BUTTON
57 : };
58 :
59 0 : AboutDialog::AboutDialog( Window* pParent, const ResId& rId) :
60 : SfxModalDialog ( pParent, rId ),
61 0 : aVersionText ( this, ResId( ABOUT_VERSION_TEXT, *rId.GetResMgr() ) ),
62 0 : aDescriptionText ( this, ResId( ABOUT_DESCRIPTION_TEXT, *rId.GetResMgr() ) ),
63 0 : aCopyrightText ( this, ResId( ABOUT_COPYRIGHT_TEXT, *rId.GetResMgr() ) ),
64 : aLogoImage ( this ),
65 0 : aLogoReplacement ( this, ResId( ABOUT_LOGO_REPLACEMENT, *rId.GetResMgr() ) ),
66 0 : aCreditsButton ( this, ResId( ABOUT_BTN_CREDITS, *rId.GetResMgr() ) ),
67 0 : aWebsiteButton ( this, ResId( ABOUT_BTN_WEBSITE, *rId.GetResMgr() ) ),
68 0 : aCancelButton ( this, ResId( ABOUT_BTN_CANCEL, *rId.GetResMgr() ) ),
69 0 : m_aVersionTextStr(ResId(ABOUT_STR_VERSION, *rId.GetResMgr()).toString().trim()),
70 0 : m_aVendorTextStr(ResId(ABOUT_STR_VENDOR, *rId.GetResMgr())),
71 0 : m_aCopyrightTextStr(ResId(ABOUT_STR_COPYRIGHT, *rId.GetResMgr())),
72 0 : m_aBasedTextStr(ResId(ABOUT_STR_BASED, *rId.GetResMgr())),
73 0 : m_aBasedDerivedTextStr(ResId(ABOUT_STR_BASED_DERIVED, *rId.GetResMgr())),
74 0 : m_aCreditsLinkStr(ResId( ABOUT_STR_LINK_CREDITS, *rId.GetResMgr())),
75 0 : m_sBuildStr(ResId(ABOUT_STR_BUILD, *rId.GetResMgr())),
76 0 : m_aDescriptionTextStr(ResId(ABOUT_STR_DESCRIPTION, *rId.GetResMgr()))
77 : {
78 : // Populate text items
79 0 : aLogoReplacement.SetText ( utl::ConfigManager::getProductName() );
80 :
81 0 : aVersionText.SetText( GetVersionString() );
82 :
83 0 : aDescriptionText.SetText( m_aDescriptionTextStr );
84 :
85 0 : rtl::OUString aCopyrightString = GetCopyrightString();
86 0 : aCopyrightText.SetText( aCopyrightString );
87 :
88 0 : StyleControls();
89 0 : LayoutControls();
90 :
91 : // Allow the button to be identifiable once they are clicked
92 0 : aCreditsButton.SetData( (void*)CREDITS_BUTTON );
93 0 : aWebsiteButton.SetData( (void*)WEBSITE_BUTTON );
94 :
95 : // Connect all handlers
96 0 : aCreditsButton.SetClickHdl( LINK( this, AboutDialog, HandleClick ) );
97 0 : aWebsiteButton.SetClickHdl( LINK( this, AboutDialog, HandleClick ) );
98 :
99 0 : aCancelButton.SetClickHdl( LINK( this, AboutDialog, CancelHdl ) );
100 :
101 0 : FreeResource();
102 :
103 : // explicit Help-Id
104 0 : SetHelpId( CMD_SID_ABOUT );
105 0 : }
106 :
107 0 : IMPL_LINK( AboutDialog, HandleClick, PushButton*, pButton )
108 : {
109 0 : rtl::OUString sURL = "";
110 :
111 : // Find which button was pressed and from this, get the URL to be opened
112 0 : AboutDialogButton* pDialogButton = (AboutDialogButton*)pButton->GetData();
113 0 : if ( pDialogButton == (AboutDialogButton*)CREDITS_BUTTON )
114 0 : sURL = m_aCreditsLinkStr;
115 0 : else if ( pDialogButton == (AboutDialogButton*)WEBSITE_BUTTON )
116 : {
117 0 : sURL = officecfg::Office::Common::Help::StartCenter::InfoURL::get();
118 0 : localizeWebserviceURI(sURL);
119 : }
120 :
121 : // If the URL is empty, don't do anything
122 0 : if ( sURL.isEmpty() )
123 0 : return 1;
124 : try
125 : {
126 : Reference< com::sun::star::system::XSystemShellExecute > xSystemShellExecute(
127 0 : com::sun::star::system::SystemShellExecute::create(::comphelper::getProcessComponentContext() ) );
128 0 : xSystemShellExecute->execute( sURL, rtl::OUString(), com::sun::star::system::SystemShellExecuteFlags::URIS_ONLY );
129 : }
130 0 : catch (const Exception&)
131 : {
132 0 : Any exc( ::cppu::getCaughtException() );
133 0 : rtl::OUString msg( ::comphelper::anyToString( exc ) );
134 0 : const SolarMutexGuard guard;
135 0 : ErrorBox aErrorBox( NULL, WB_OK, msg );
136 0 : aErrorBox.SetText( GetText() );
137 0 : aErrorBox.Execute();
138 : }
139 :
140 0 : return 1;
141 : }
142 :
143 0 : void AboutDialog::StyleControls()
144 : {
145 : // Make all the controls have a transparent background
146 0 : aLogoImage.SetBackground();
147 0 : aLogoReplacement.SetPaintTransparent( sal_True );
148 0 : aVersionText.SetPaintTransparent( sal_True );
149 0 : aDescriptionText.SetPaintTransparent( sal_True );
150 0 : aCopyrightText.SetPaintTransparent( sal_True );
151 :
152 0 : Font aLabelFont = GetSettings().GetStyleSettings().GetLabelFont();
153 0 : Font aLargeFont = aLabelFont;
154 0 : aLargeFont.SetSize( Size( 0, aLabelFont.GetSize().Height() * 3 ) );
155 :
156 : // Logo Replacement Text
157 0 : aLogoReplacement.SetControlFont( aLargeFont );
158 0 : aLogoReplacement.SetTextSelectable( sal_False );
159 :
160 : // Description Text
161 0 : aLargeFont.SetSize( Size( 0, aLabelFont.GetSize().Height() * 1.3 ) );
162 0 : aDescriptionText.SetControlFont( aLargeFont );
163 0 : aDescriptionText.SetTextSelectable( sal_False );
164 :
165 : // Version Text
166 0 : aLargeFont.SetSize( Size( 0, aLabelFont.GetSize().Height() * 1.2 ) );
167 0 : aVersionText.SetControlFont( aLargeFont );
168 0 : aVersionText.EnableCursor( sal_False );
169 :
170 : // Copyright Text
171 0 : aCopyrightText.SetTextSelectable( sal_False );
172 :
173 : // If not in high-contrast mode, hard-code colors
174 0 : if ( !(Application::GetSettings().GetStyleSettings().GetHighContrastMode()) )
175 : {
176 0 : aLogoReplacement.SetControlForeground( Color( 51, 51, 51 ) );
177 0 : aVersionText.SetControlForeground( Color( 102, 102, 102 ) );
178 0 : aDescriptionText.SetControlForeground( Color( 51, 51, 51 ) );
179 0 : aCopyrightText.SetControlForeground( Color( 102, 102, 102 ) );
180 : }
181 :
182 :
183 0 : aCancelButton.GrabFocus();
184 0 : }
185 :
186 0 : void AboutDialog::LayoutControls()
187 : {
188 : // Get the size of the screen
189 0 : Rectangle aScreenRect = Application::GetScreenPosSizePixel( (unsigned int)0 );
190 : // Obtain an appropriate text width from the size of the screen
191 0 : sal_Int32 aIdealTextWidth = aScreenRect.GetWidth() / 2.4;
192 :
193 0 : sal_Int32 aDialogBorder = 12;
194 0 : Size aDialogSize ( aIdealTextWidth + aDialogBorder * 2, 0 );
195 :
196 : // Preliminarily layout buttons, so we see if we need a wider window
197 0 : Size aButtonSize;
198 0 : Point aButtonPos;
199 0 : sal_Int32 aButtonsWidth = 0;
200 0 : LayoutButtons( aDialogSize.Width(), aDialogBorder, aButtonPos, aButtonSize,
201 0 : aButtonsWidth );
202 :
203 0 : if (aButtonsWidth > 0)
204 0 : aDialogSize.Width() += aButtonsWidth;
205 :
206 : // Render and Position Logo
207 0 : Size aLogoSize( aIdealTextWidth, aIdealTextWidth / 20 );
208 0 : Point aLogoPos( 0, 0 );
209 :
210 0 : if( Application::LoadBrandSVG("flat_logo", aLogoBitmap) &&
211 0 : !aLogoBitmap.IsEmpty() )
212 : {
213 0 : const float aLogoWidthHeightRatio = (float)aLogoBitmap.GetSizePixel().Width() / (float)aLogoBitmap.GetSizePixel().Height();
214 0 : aLogoSize.Width() = aDialogSize.Width() ;
215 0 : aLogoSize.Height() = aLogoSize.Width() / aLogoWidthHeightRatio ;
216 0 : aLogoBitmap.Scale(aLogoSize);
217 :
218 0 : aLogoImage.SetImage( Image( aLogoBitmap ) );
219 0 : aLogoImage.SetPosSizePixel( aLogoPos, aLogoSize );
220 0 : aLogoImage.Show();
221 : }
222 : else
223 : {
224 0 : aLogoPos.X() = aDialogBorder;
225 0 : aLogoPos.Y() = aDialogBorder;
226 0 : aLogoSize = aLogoReplacement.CalcMinimumSize();
227 0 : aLogoSize.Width() = aIdealTextWidth;
228 0 : aLogoReplacement.SetPosSizePixel( aLogoPos, aLogoSize );
229 : }
230 :
231 : // Position version text
232 0 : sal_Int32 aLogoVersionSpacing = aLogoSize.Height() * 0.15;
233 : Point aVersionPos( aDialogBorder,
234 0 : aLogoPos.Y() + aLogoSize.Height() + aLogoVersionSpacing );
235 0 : Size aVersionSize = aVersionText.GetSizePixel();
236 0 : aVersionSize.Width() = aIdealTextWidth;
237 0 : aVersionText.SetPosSizePixel( aVersionPos, aVersionSize );
238 0 : aVersionSize = aVersionText.CalcMinimumSize();
239 0 : aVersionText.SetSizePixel( aVersionSize );
240 :
241 : // Position description text
242 0 : sal_Int32 aVersionDescriptionSpacing = aLogoSize.Height() * 0.45;
243 0 : Point aDescriptionPos( aDialogBorder, aVersionPos.Y() + aVersionSize.Height() + aVersionDescriptionSpacing );
244 0 : Size aDescriptionSize = aDescriptionText.GetSizePixel();
245 0 : aDescriptionSize.Width() = aIdealTextWidth;
246 0 : aDescriptionText.SetPosSizePixel( aDescriptionPos, aDescriptionSize );
247 0 : aDescriptionSize = aDescriptionText.CalcMinimumSize();
248 0 : aDescriptionText.SetSizePixel( aDescriptionSize );
249 :
250 : // Layout copyright text
251 0 : Point aCopyrightPos( aDialogBorder, aDescriptionPos.Y() + aDescriptionText.GetSizePixel().Height() + aVersionDescriptionSpacing );
252 0 : Size aCopyrightSize = aCopyrightText.GetSizePixel();
253 0 : aCopyrightSize.Width() = aIdealTextWidth;
254 0 : aCopyrightText.SetPosSizePixel( aCopyrightPos, aCopyrightSize );
255 0 : aCopyrightSize = aCopyrightText.CalcMinimumSize();
256 0 : aCopyrightSize.Width() = aIdealTextWidth;
257 0 : aCopyrightText.SetSizePixel( aCopyrightSize );
258 :
259 : // Move buttons into final place
260 0 : sal_Int32 aButtonPosY = aDialogBorder + aCopyrightPos.Y() +
261 0 : aCopyrightText.GetSizePixel().Height() + aVersionDescriptionSpacing;
262 :
263 0 : MoveControl(aCreditsButton, 0, aButtonPosY);
264 0 : MoveControl(aWebsiteButton, 0, aButtonPosY);
265 0 : MoveControl(aCancelButton, 0, aButtonPosY);
266 :
267 : // The centers everything again, if aDialogSize.Width() has become wider
268 : // before; the -20 "fixes" a weird text centering bug
269 0 : MoveControl(aVersionText, (aDialogSize.Width() - aVersionText.GetSizePixel().Width() - 20)/2, 0);
270 0 : MoveControl(aDescriptionText, (aDialogSize.Width() - aDescriptionText.GetSizePixel().Width() - 20)/2, 0);
271 0 : MoveControl(aCopyrightText, (aDialogSize.Width() - aCopyrightText.GetSizePixel().Width() - 20)/2, 0);
272 :
273 0 : aDialogSize.Height() = aButtonPosY + aButtonSize.Height() + aDialogBorder;
274 :
275 :
276 : // Layout background image
277 0 : if ( !(Application::GetSettings().GetStyleSettings().GetHighContrastMode()) &&
278 0 : Application::LoadBrandSVG("shell/about", aBackgroundBitmap) &&
279 0 : !aBackgroundBitmap.IsEmpty() )
280 : {
281 0 : const float aBackgroundWidthHeightRatio = (float)aBackgroundBitmap.GetSizePixel().Width() /
282 0 : (float)aBackgroundBitmap.GetSizePixel().Height();
283 0 : Size aBackgroundSize (aDialogSize.Width(), aDialogSize.Width() / aBackgroundWidthHeightRatio );
284 :
285 0 : if ( aBackgroundSize.Height() < aDialogSize.Height())
286 : {
287 0 : aBackgroundSize.Width() = aDialogSize.Height() * aBackgroundWidthHeightRatio ;
288 0 : aBackgroundSize.Height() = aDialogSize.Height();
289 : }
290 0 : aBackgroundBitmap.Scale(aBackgroundSize);
291 : }
292 :
293 0 : SetOutputSizePixel( aDialogSize );
294 :
295 0 : }
296 :
297 0 : void AboutDialog::LayoutButtons(sal_Int32 aDialogWidth, sal_Int32 aDialogBorder,
298 : Point& aButtonPos, Size& aButtonSize,
299 : sal_Int32& aButtonsWidth )
300 : {
301 : // Position credits button
302 0 : sal_Int32 aButtonVPadding = 5;
303 0 : sal_Int32 aButtonHPadding = 4;
304 0 : sal_Int32 aAdjacentButtonSpacing = 15;
305 0 : sal_Int32 aCreditsButtonWidth = aCreditsButton.CalcMinimumSize().Width();
306 0 : sal_Int32 aWebsiteButtonWidth = aWebsiteButton.CalcMinimumSize().Width();
307 0 : sal_Int32 aCancelButtonWidth = aCancelButton.CalcMinimumSize().Width();
308 0 : sal_Int32 aLargestButtonWidth = 70;
309 :
310 0 : if ( aLargestButtonWidth < aCreditsButtonWidth )
311 0 : aLargestButtonWidth = aCreditsButtonWidth;
312 0 : if ( aLargestButtonWidth < aWebsiteButtonWidth )
313 0 : aLargestButtonWidth = aWebsiteButtonWidth;
314 0 : if ( aLargestButtonWidth < aCancelButtonWidth )
315 0 : aLargestButtonWidth = aCancelButtonWidth;
316 :
317 0 : aButtonSize.Width() = aLargestButtonWidth + ( 2 * aButtonHPadding );
318 0 : aButtonSize.Height() = aWebsiteButton.CalcMinimumSize().Height() + ( 2 * aButtonVPadding );
319 :
320 0 : aCreditsButton.SetSizePixel( aButtonSize );
321 0 : aWebsiteButton.SetSizePixel( aButtonSize );
322 0 : aCancelButton.SetSizePixel( aButtonSize );
323 :
324 0 : sal_Int32 aButtonSpacing = aDialogWidth - ( aDialogBorder * 2 ) - ( aButtonSize.Width() * 3 ) - aAdjacentButtonSpacing ;
325 0 : if (aButtonSpacing < aAdjacentButtonSpacing)
326 : {
327 0 : aButtonsWidth = aAdjacentButtonSpacing - aButtonSpacing;
328 0 : aButtonSpacing = aAdjacentButtonSpacing;
329 : }
330 :
331 0 : aButtonPos.X() = aDialogBorder;
332 0 : aButtonPos.Y() = 0;
333 :
334 0 : aCreditsButton.SetPosPixel( aButtonPos );
335 :
336 0 : aButtonPos.X() += aButtonSize.Width() + aAdjacentButtonSpacing;
337 0 : aWebsiteButton.SetPosPixel( aButtonPos );
338 :
339 0 : aButtonPos.X() += aButtonSize.Width() + aButtonSpacing;
340 0 : aCancelButton.SetPosPixel( aButtonPos );
341 :
342 :
343 0 : }
344 :
345 0 : void AboutDialog::MoveControl(Control& rControl, sal_Int32 X, sal_Int32 Y)
346 : {
347 0 : Point aControlPos = rControl.GetPosPixel();
348 0 : aControlPos.X() += X;
349 0 : aControlPos.Y() += Y;
350 0 : rControl.SetPosPixel(aControlPos);
351 0 : }
352 :
353 0 : void AboutDialog::Paint( const Rectangle& rRect )
354 : {
355 0 : SetClipRegion( rRect );
356 0 : Point aPos ( rRect.GetWidth() - aBackgroundBitmap.GetSizePixel().Width(), rRect.GetHeight() - aBackgroundBitmap.GetSizePixel().Height() );
357 0 : DrawBitmapEx( aPos, aBackgroundBitmap );
358 0 : }
359 :
360 0 : rtl::OUString AboutDialog::GetBuildId()
361 : {
362 0 : rtl::OUString sDefault;
363 0 : rtl::OUString sBuildId(utl::Bootstrap::getBuildVersion(sDefault));
364 0 : if (!sBuildId.isEmpty())
365 0 : return sBuildId;
366 :
367 0 : sBuildId = utl::Bootstrap::getBuildIdData(sDefault);
368 :
369 0 : if (!sBuildId.isEmpty())
370 : {
371 0 : sal_Int32 nIndex = 0;
372 0 : return sBuildId.getToken( 0, '-', nIndex );
373 : }
374 :
375 : OSL_ENSURE( !sBuildId.isEmpty(), "No BUILDID in bootstrap file" );
376 0 : return sBuildId;
377 : }
378 :
379 0 : rtl::OUString AboutDialog::GetVersionString()
380 : {
381 0 : rtl::OUString sVersion = m_aVersionTextStr;
382 :
383 0 : rtl::OUString sBuildId = GetBuildId();
384 :
385 0 : if (!sBuildId.trim().isEmpty())
386 : {
387 0 : sVersion += " ";
388 0 : if (m_sBuildStr.indexOf("$BUILDID") == -1)
389 : {
390 : SAL_WARN( "cui.dialogs", "translated Build Id string in translations doesn't contain $BUILDID placeholder" );
391 0 : m_sBuildStr += " $BUILDID";
392 : }
393 0 : sVersion += m_sBuildStr.replaceAll("$BUILDID", sBuildId);
394 : }
395 :
396 : #ifdef EXTRA_BUILDID
397 : sVersion += "\n";
398 : sVersion += EXTRA_BUILDID;
399 : #endif
400 :
401 0 : return sVersion;
402 : }
403 :
404 0 : rtl::OUString AboutDialog::GetCopyrightString()
405 : {
406 0 : rtl::OUString aCopyrightString = m_aVendorTextStr;
407 0 : aCopyrightString += "\n";
408 :
409 0 : aCopyrightString += m_aCopyrightTextStr;
410 0 : aCopyrightString += "\n";
411 :
412 0 : if (utl::ConfigManager::getProductName().equals("LibreOffice"))
413 0 : aCopyrightString += m_aBasedTextStr;
414 : else
415 0 : aCopyrightString += m_aBasedDerivedTextStr;
416 :
417 0 : return aCopyrightString;
418 : }
419 :
420 0 : IMPL_LINK_NOARG(AboutDialog, CancelHdl)
421 : {
422 0 : Close();
423 0 : return 0;
424 : }
425 :
426 0 : sal_Bool AboutDialog::Close()
427 : {
428 0 : EndDialog( RET_OK );
429 0 : return sal_False;
430 : }
431 :
432 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|