xref: /aoo42x/main/cui/source/dialogs/about.cxx (revision 0504c4ef)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_cui.hxx"
26 
27 #include <comphelper/processfactory.hxx>
28 #include <dialmgr.hxx>
29 #include <osl/file.hxx>
30 #include <rtl/bootstrap.hxx>
31 //#include <rtl/ustrbuf.hxx>
32 #include <sfx2/sfxcommands.h>
33 #include <sfx2/sfxdefs.hxx>
34 #include <sfx2/sfxuno.hxx>
35 #include <svtools/filter.hxx>
36 #include <svtools/svtools.hrc>
37 #include <tools/stream.hxx>
38 #include <tools/urlobj.hxx>
39 #include <unotools/bootstrap.hxx>
40 #include <unotools/configmgr.hxx>
41 #include <vcl/graph.hxx>
42 #include <vcl/imagerepository.hxx>
43 #include <vcl/msgbox.hxx>
44 #include <vcl/svapp.hxx>
45 #include <vcl/tabctrl.hxx>
46 #include <vcl/tabdlg.hxx>
47 #include <vcl/tabpage.hxx>
48 
49 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
50 #include <com/sun/star/system/SystemShellExecute.hpp>
51 #include <com/sun/star/uno/Any.h>
52 
53 #include "about.hxx"
54 #include "about.hrc"
55 
56 #define _STRINGIFY(x) #x
57 #define STRINGIFY(x) _STRINGIFY(x)
58 
59 /* On Windows/OS2, all the three files have .txt extension
60    and the README file name is in lowercase
61    Readme files are localized and have the locale in their file name:
62    README_de README_en-US
63 */
64 #if defined(WNT) || defined(OS2)
65 #define FILE_EXTENSION  ".txt"
66 #define README_FILE     "readme"
67 #else
68 #define FILE_EXTENSION
69 #define README_FILE     "README"
70 #endif
71 #define LICENSE_FILE    "LICENSE" FILE_EXTENSION
72 #define NOTICE_FILE     "NOTICE"  FILE_EXTENSION
73 
74 // Dir where the files are located
75 #define OOO_DIR_SHARE_README  "${OOO_BASE_DIR}/share/readme/"
76 
77 using namespace com::sun::star;
78 
79 namespace
80 {
81 
82 	static void lcl_layoutFixedText( FixedText &rControl,
83 									 const Point& aPos,
84 									 Size &aSize,
85 									 const long nTextWidth )
86 	{
87 		aSize = rControl.GetSizePixel();
88 		// change the width
89 		aSize.Width() = nTextWidth;
90 		// set Position and Size, to calculate the minimum size
91 		// this will update the Height
92 		rControl.SetPosSizePixel( aPos, aSize );
93 		aSize = rControl.CalcMinimumSize();
94 		// update the size with the right Height
95 		rControl.SetSizePixel( aSize );
96 	}
97 
98 	static void lcl_layoutEdit( Edit &rControl,
99 								const Point& aPos,
100 								Size &aSize,
101 								const long nTextWidth )
102 	{
103 		aSize = rControl.GetSizePixel();
104 		// change the width
105 		aSize.Width() = nTextWidth;
106 		// set Position and Size, to calculate the minimum size
107 		// this will update the Height
108 		rControl.SetPosSizePixel( aPos, aSize );
109 		aSize = rControl.CalcMinimumSize();
110 		// update the size with the right Height
111 		rControl.SetSizePixel( aSize );
112 	}
113 
114 	static void lcl_readTxtFile( const rtl::OUString &rFile, rtl::OUString &sText )
115 	{
116 		rtl::OUString sFile( rFile );
117 		rtl::Bootstrap::expandMacros( sFile );
118 		osl::File aFile(sFile);
119 		if ( aFile.open(OpenFlag_Read) == osl::FileBase::E_None )
120 		{
121 			osl::DirectoryItem aItem;
122 			osl::DirectoryItem::get(sFile, aItem);
123 
124 			osl::FileStatus aStatus(FileStatusMask_FileSize);
125 			aItem.getFileStatus(aStatus);
126 
127 			sal_uInt64 nBytesRead = 0;
128 			sal_uInt64 nPosition = 0;
129 			sal_uInt32 nBytes = (sal_uInt32)aStatus.getFileSize();
130 
131 			sal_Char *pBuffer = new sal_Char[nBytes];
132 
133 			while ( aFile.read( pBuffer + nPosition,
134 								nBytes-nPosition,
135 								nBytesRead ) == osl::FileBase::E_None
136 					&& nPosition + nBytesRead < nBytes)
137 			{
138 				nPosition += nBytesRead;
139 			}
140 
141 			OSL_ENSURE( nBytes < STRING_MAXLEN, "Text file has too much bytes!" );
142 			if ( nBytes > STRING_MAXLEN )
143 				nBytes = STRING_MAXLEN - 1;
144 
145 			sText = rtl::OUString( pBuffer,
146 								nBytes,
147 								RTL_TEXTENCODING_UTF8,
148 								OSTRING_TO_OUSTRING_CVTFLAGS
149 								| RTL_TEXTTOUNICODE_FLAGS_GLOBAL_SIGNATURE);
150 			delete[] pBuffer;
151 		}
152 	}
153 
154 	class ReadmeDialog;
155 
156 	class ReadmeTabPage : public TabPage
157 	{
158 	private:
159 		MultiLineEdit maText;
160 		String        msText;
161 
162 	public:
163 		ReadmeTabPage(Window *pParent, const String &sText);
164 		~ReadmeTabPage();
165 
166 		void Adjust(const Size &aSz, const Size &a6Size);
167 	};
168 
169 	ReadmeTabPage::ReadmeTabPage(Window *pParent, const String &sText)
170 		: TabPage(pParent, CUI_RES( RID_CUI_README_TBPAGE))
171 		,maText( this, CUI_RES( RID_CUI_README_TBPAGE_EDIT ))
172 		,msText( sText )
173 	{
174 		FreeResource();
175 
176 		maText.SetText(msText);
177 		maText.Show();
178 	}
179 
180 	ReadmeTabPage::~ReadmeTabPage()
181 	{
182 	}
183 
184 	void ReadmeTabPage::Adjust(const Size &aSz, const Size &a6Size)
185 	{
186 		long nDlgMargin  = a6Size.Width() * 2;
187 		long nCtrlMargin = a6Size.Height() * 2;
188 		maText.SetPosPixel( Point(a6Size.Width(), a6Size.Height()) );
189 		maText.SetSizePixel( Size(aSz.Width() - nDlgMargin, aSz.Height() - nCtrlMargin) );
190 	}
191 
192 	class ReadmeDialog : public ModalDialog
193 	{
194 	private:
195 		TabControl      maTabCtrl;
196 		OKButton        maBtnOK;
197 
198 		ReadmeTabPage  *maReadmeTabPage;
199 		ReadmeTabPage  *maLicenseTabPage;
200 		ReadmeTabPage  *maNoticeTabPage;
201 
202 		DECL_LINK( ActivatePageHdl, TabControl * );
203 		DECL_LINK( DeactivatePageHdl, TabControl * );
204 
205 	public:
206 		ReadmeDialog( Window* );
207 		~ReadmeDialog();
208 	};
209 
210 	ReadmeDialog::ReadmeDialog( Window * pParent )
211 		: ModalDialog( pParent, CUI_RES( RID_CUI_README_DLG ) )
212 		, maTabCtrl( this, CUI_RES(RID_CUI_README_TBCTL) )
213 		, maBtnOK( this, CUI_RES(RID_CUI_README_OKBTN) )
214 		, maReadmeTabPage(0)
215 		, maLicenseTabPage(0)
216 		, maNoticeTabPage(0)
217 	{
218 		FreeResource();
219 
220 		maTabCtrl.Show();
221 
222 		// Notice and License are not localized
223 		const rtl::OUString sLicense( RTL_CONSTASCII_USTRINGPARAM( OOO_DIR_SHARE_README LICENSE_FILE ) );
224 		const rtl::OUString sNotice( RTL_CONSTASCII_USTRINGPARAM(  OOO_DIR_SHARE_README NOTICE_FILE ) );
225 
226 		// get localized README
227 		rtl::OUStringBuffer aBuff;
228 		lang::Locale aLocale = Application::GetSettings().GetUILocale();
229 		aBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( OOO_DIR_SHARE_README README_FILE "_" ) );
230 		aBuff.append( aLocale.Language );
231 		if ( aLocale.Country.getLength() )
232 		{
233 			aBuff.append( sal_Unicode( '-') );
234 			aBuff.append( aLocale.Country );
235 			if ( aLocale.Variant.getLength() )
236 			{
237 				aBuff.append( sal_Unicode( '-' ) );
238 				aBuff.append( aLocale.Variant );
239 			}
240 		}
241 #if defined(WNT) || defined(OS2)
242 		aBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( FILE_EXTENSION ) );
243 #endif
244 
245 		rtl::OUString sReadmeTxt, sLicenseTxt, sNoticeTxt;
246 		lcl_readTxtFile( aBuff.makeStringAndClear(), sReadmeTxt );
247 		lcl_readTxtFile( sLicense, sLicenseTxt );
248 		lcl_readTxtFile( sNotice, sNoticeTxt );
249 
250 		maReadmeTabPage = new ReadmeTabPage( &maTabCtrl, sReadmeTxt );
251 		maLicenseTabPage = new ReadmeTabPage( &maTabCtrl, sLicenseTxt );
252 		maNoticeTabPage = new ReadmeTabPage( &maTabCtrl, sNoticeTxt );
253 
254 		maTabCtrl.SetTabPage( RID_CUI_READMEPAGE, maReadmeTabPage );
255 		maTabCtrl.SetTabPage( RID_CUI_LICENSEPAGE, maLicenseTabPage );
256 		maTabCtrl.SetTabPage( RID_CUI_NOTICEPAGE, maNoticeTabPage );
257 
258 		maTabCtrl.SelectTabPage( RID_CUI_READMEPAGE );
259 
260 		Size aTpSz  = maReadmeTabPage->GetOutputSizePixel();
261 		Size a6Size = maReadmeTabPage->LogicToPixel( Size( 6, 6 ), MAP_APPFONT );
262 
263 		maReadmeTabPage->Adjust( aTpSz, a6Size );
264 		maLicenseTabPage->Adjust( aTpSz, a6Size );
265 		maNoticeTabPage->Adjust( aTpSz, a6Size );
266 
267 		Size aDlgSize = GetOutputSizePixel();
268 		Size aOkBtnSz = maBtnOK.GetSizePixel();
269 		Point aOKPnt( aDlgSize.Width() / 2 - aOkBtnSz.Width() / 2 , maBtnOK.GetPosPixel().Y() );
270 		maBtnOK.SetPosPixel( aOKPnt );
271 	}
272 
273 	ReadmeDialog::~ReadmeDialog()
274 	{
275 		delete maReadmeTabPage;
276 		delete maLicenseTabPage;
277 		delete maNoticeTabPage;
278 	}
279 }
280 
281 // -----------------------------------------------------------------------
282 
283 AboutDialog::AboutDialog( Window* pParent, const ResId & rId ) :
284 	SfxModalDialog( pParent, rId ),
285 	maOKButton( this, ResId( RID_CUI_ABOUT_BTN_OK, *rId.GetResMgr() ) ),
286 	maReadmeButton( this, ResId( RID_CUI_ABOUT_BTN_README, *rId.GetResMgr() ) ),
287 	maVersionText( this, ResId( RID_CUI_ABOUT_FTXT_VERSION, *rId.GetResMgr() ) ),
288 	maBuildInfoEdit( this, ResId( RID_CUI_ABOUT_FTXT_BUILDDATA, *rId.GetResMgr() ) ),
289 	maCopyrightEdit( this, ResId( RID_CUI_ABOUT_FTXT_COPYRIGHT, *rId.GetResMgr() ) ),
290 	maCreditsLink( this, ResId( RID_CUI_ABOUT_FTXT_WELCOME_LINK, *rId.GetResMgr() ) )
291 //	maCopyrightTextStr( ResId( RID_CUI_ABOUT_STR_COPYRIGHT, *rId.GetResMgr() ) )
292 {
293 	bool bLoad = vcl::ImageRepository::loadBrandingImage(
294 			rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("about")),
295 			maAppLogo );
296 	OSL_ENSURE( bLoad, "Can't load about image");
297 
298 	bLoad = vcl::ImageRepository::loadBrandingImage(
299 			rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("logo")),
300 			maMainLogo );
301 	OSL_ENSURE( bLoad, "Can't load logo image");
302 
303 	const String vendor( ResId( RID_CUI_ABOUT_STR_COPYRIGHT_VENDOR, *rId.GetResMgr() ) );
304 	String createdRes( ResId( RID_CUI_ABOUT_STR_CREATED, *rId.GetResMgr() ) );
305 	if ( !vendor.EqualsAscii("Apache Software Foundation") ) {
306 		createdRes = String( ResId( RID_CUI_ABOUT_STR_CREATED_VENDOR, *rId.GetResMgr() ));
307 	}
308 	const String copyrightAcknowledge( ResId( RID_CUI_ABOUT_STR_ACKNOWLEDGE, *rId.GetResMgr() ) );
309 
310 	rtl::OUStringBuffer sbcopyright(250);
311 	sbcopyright.appendAscii("Copyright ");
312 	sbcopyright.append((sal_Unicode)0x00a9);
313 	sbcopyright.appendAscii(" ");
314 	rtl::OUString sYear( RTL_CONSTASCII_USTRINGPARAM("2023") );
315 	if (vendor.EqualsAscii("Apache Software Foundation")) {
316 		sbcopyright.append(sYear);
317 		sbcopyright.appendAscii(" The Apache Software Foundation.\n\n");
318 	} else {
319 #ifdef COPYRIGHT_YEAR
320 		const rtl::OUString sDefYear( RTL_CONSTASCII_USTRINGPARAM( STRINGIFY( COPYRIGHT_YEAR ) ) );
321 		if ( sDefYear.getLength() > 0 )
322 		{
323 			sYear = sDefYear;
324 		}
325 #endif
326 		sbcopyright.append(sYear);
327 		sbcopyright.appendAscii(" ");
328 		sbcopyright.append(vendor);
329 		sbcopyright.appendAscii(".\nPortion copyright The Apache Software Foundation.\n\n");
330 	}
331 	sbcopyright.append( createdRes );
332 	sbcopyright.appendAscii("\n\n");
333 	sbcopyright.append( copyrightAcknowledge );
334 	maCopyrightTextStr = sbcopyright.makeStringAndClear();
335 
336 	InitControls();
337 
338 	// set links
339 	maReadmeButton.SetClickHdl( LINK( this, AboutDialog, ShowReadme_Impl ) );
340 	maCreditsLink.SetClickHdl( LINK( this, AboutDialog, OpenLinkHdl_Impl ) );
341 
342 	FreeResource();
343 
344 	SetHelpId( CMD_SID_ABOUT );
345 }
346 
347 // -----------------------------------------------------------------------
348 
349 AboutDialog::~AboutDialog()
350 {
351 }
352 
353 // -----------------------------------------------------------------------
354 
355 void AboutDialog::InitControls()
356 {
357 	// apply font, background et al.
358 	ApplyStyleSettings();
359 
360 	// set strings
361 	maCopyrightEdit.SetText( maCopyrightTextStr );
362 	maBuildInfoEdit.SetText( GetBuildVersionString() );
363 	maCreditsLink.SetURL( maCreditsLink.GetText() );
364 
365 	// determine size and position of the dialog & elements
366 	Size aDlgSize;
367 	LayoutControls( aDlgSize );
368 
369 	// Change the width of the dialog
370 	SetOutputSizePixel( aDlgSize );
371 }
372 
373 // -----------------------------------------------------------------------
374 
375 void AboutDialog::ApplyStyleSettings()
376 {
377 	// transparent font
378 	Font aFont = GetFont();
379 	aFont.SetTransparent( sal_True );
380 	SetFont( aFont );
381 
382 	// set for background and text the correct system color
383 	const StyleSettings& rSettings = GetSettings().GetStyleSettings();
384 	Color aWindowColor( rSettings.GetWindowColor() );
385 	Wallpaper aWall( aWindowColor );
386 	SetBackground( aWall );
387 
388 	Font aNewFont( maCopyrightEdit.GetFont() );
389 	aNewFont.SetTransparent( sal_True );
390 
391 	maVersionText.SetFont( aNewFont );
392 	maCopyrightEdit.SetFont( aNewFont );
393 
394 	maVersionText.SetBackground(aWall);
395 	maCopyrightEdit.SetBackground(aWall);
396 	maBuildInfoEdit.SetBackground(aWall);
397 	maCreditsLink.SetBackground(aWall);
398 
399 	Color aTextColor( rSettings.GetWindowTextColor() );
400 	maVersionText.SetControlForeground( aTextColor );
401 	maCopyrightEdit.SetControlForeground( aTextColor );
402 	maBuildInfoEdit.SetControlForeground( aTextColor );
403 	maCreditsLink.SetControlForeground();
404 
405 	Size aSmaller = aNewFont.GetSize();
406 	aSmaller.Width() = (long) (aSmaller.Width() * 0.75);
407 	aSmaller.Height() = (long) (aSmaller.Height() * 0.75);
408 	aNewFont.SetSize( aSmaller );
409 
410 	maBuildInfoEdit.SetFont( aNewFont );
411 
412 	// the following is a hack to force the MultiLineEdit update its settings
413 	// in order to reflect the Font
414 	// See
415 	//      Window::SetControlFont
416 	//      MultiLineEdit::StateChanged
417 	//      MultiLineEdit::ImplInitSettings
418 	// TODO Override SetFont in MultiLineEdit and do the following,
419 	// otherwise SetFont has no effect at all!
420 	aSmaller = PixelToLogic( aSmaller, MAP_POINT );
421 	aNewFont.SetSize( aSmaller );
422 	maBuildInfoEdit.SetControlFont( aNewFont );
423 }
424 
425 // -----------------------------------------------------------------------
426 
427 void AboutDialog::LayoutControls( Size& aDlgSize )
428 {
429 	Size aMainLogoSz = maMainLogo.GetSizePixel();
430 	Size aAppLogoSiz = maAppLogo.GetSizePixel();
431 
432 	aDlgSize = GetOutputSizePixel();
433 	long nCol1 = aMainLogoSz.Width();
434 	long nCol2 = aAppLogoSiz.Width() ? aAppLogoSiz.Width() : aDlgSize.Width();
435 
436 	Size a6Size      = maVersionText.LogicToPixel( Size( 6, 6 ), MAP_APPFONT );
437 	long nDlgMargin  = a6Size.Width() * 2;
438 	long nCtrlMargin = a6Size.Height() * 2;
439 	long nTextWidth  = nCol2 - nDlgMargin;
440 	long nY          = aAppLogoSiz.Height() + a6Size.Height();
441 
442 	aDlgSize.Width() = nCol1 + a6Size.Width() + nCol2;
443 
444 	Point aPos( nCol1 + a6Size.Width(), nY );
445 	Size aSize;
446 	// layout fixed text control
447 	lcl_layoutFixedText( maVersionText, aPos, aSize, nTextWidth );
448 	nY += aSize.Height() + a6Size.Height();
449 
450 	// Multiline edit with Build info
451 	aPos.Y() = nY;
452 	lcl_layoutEdit( maBuildInfoEdit, aPos, aSize, nTextWidth );
453 	nY += aSize.Height() + a6Size.Height();
454 
455 	// Multiline edit with Copyright-Text
456 	aPos.Y() = nY;
457 	lcl_layoutEdit( maCopyrightEdit, aPos, aSize, nTextWidth );
458 	nY += aSize.Height() + a6Size.Height();
459 
460 	// Hyperlink
461 	aPos.Y() = nY;
462 	lcl_layoutFixedText( maCreditsLink, aPos, aSize, nTextWidth );
463 	nY += aSize.Height();
464 
465 	nY = std::max( nY, aMainLogoSz.Height() );
466 	nY += nCtrlMargin;
467 
468 	// logos position
469 	maMainLogoPos = Point( 0, nY / 2 - aMainLogoSz.Height() / 2 );
470 	maAppLogoPos = Point( nCol1 + a6Size.Width(), 0 );
471 
472 	// OK-Button-Position (at the bottom and centered)
473 	Size aOKSiz = maOKButton.GetSizePixel();
474 	Point aOKPnt( ( aDlgSize.Width() - aOKSiz.Width() ) - a6Size.Width(), nY );
475 	maOKButton.SetPosPixel( aOKPnt );
476 
477 	maReadmeButton.SetPosPixel( Point(a6Size.Width(), nY) );
478 
479 	aDlgSize.Height() = aOKPnt.Y() + aOKSiz.Height() + a6Size.Width();
480 }
481 
482 // -----------------------------------------------------------------------
483 
484 const rtl::OUString AboutDialog::GetBuildId() const
485 {
486 	rtl::OUString sDefault;
487 
488 	// Get buildid from version[rc|.ini]
489 	rtl::OUString sBuildId( utl::Bootstrap::getBuildIdData( sDefault ) );
490 	OSL_ENSURE( sBuildId.getLength() > 0, "No BUILDID in bootstrap file" );
491 	rtl::OUStringBuffer sBuildIdBuff( sBuildId );
492 
493 	// Get ProductSource from version[rc|.ini]
494 	rtl::OUString sProductSource( utl::Bootstrap::getProductSource( sDefault ) );
495 	OSL_ENSURE( sProductSource.getLength() > 0, "No ProductSource in bootstrap file" );
496 
497 	// the product source is something like "AOO340",
498 	// while the build id is something like "340m1(Build:9590)"
499 	// For better readability, strip the duplicate ProductMajor ("340").
500 	if ( sProductSource.getLength() )
501 	{
502 		sal_Int32 nMajorLength = sProductSource.getLength() - 3;
503 		bool bMatchingUPD =
504 				( sProductSource.getLength() >= 3 )
505 			&&	( sBuildId.getLength() >= nMajorLength )
506 			&&	( sProductSource.copy( 3 ) == sBuildId.copy( 0, nMajorLength ) );
507 		OSL_ENSURE( bMatchingUPD, "BUILDID and ProductSource do not match in their UPD" );
508 		if ( bMatchingUPD )
509 			sProductSource = sProductSource.copy( 0, sProductSource.getLength() - nMajorLength );
510 
511 		// prepend the product source
512 		sBuildIdBuff.insert( 0, sProductSource );
513 	}
514 
515 	return sBuildIdBuff.makeStringAndClear();
516 }
517 
518 // -----------------------------------------------------------------------
519 
520 const rtl::OUString AboutDialog::GetBuildVersionString() const
521 {
522 	rtl::OUStringBuffer aBuildString( GetBuildId() );
523 	rtl::OUString sRevision( utl::Bootstrap::getRevisionInfo() );
524 
525 	if ( sRevision.getLength() > 0 )
526 	{
527 		aBuildString.appendAscii( RTL_CONSTASCII_STRINGPARAM( "  -  Rev. " ) );
528 		aBuildString.append( sRevision );
529 	}
530 
531 #ifdef BUILD_VER_STRING
532 	rtl::OUString sBuildVer( RTL_CONSTASCII_USTRINGPARAM( STRINGIFY( BUILD_VER_STRING ) ) );
533 	if ( sBuildVer.getLength() > 0 )
534 	{
535 		aBuildString.append( sal_Unicode( '\n' ) );
536 		aBuildString.append( sBuildVer );
537 	}
538 #endif
539 
540 	return aBuildString.makeStringAndClear();
541 }
542 
543 // -----------------------------------------------------------------------
544 
545 sal_Bool AboutDialog::Close()
546 {
547 	EndDialog( RET_OK );
548 	return( sal_False );
549 }
550 
551 // -----------------------------------------------------------------------
552 
553 void AboutDialog::Paint( const Rectangle& rRect )
554 {
555 	SetClipRegion( rRect );
556 
557 	// workaround to ensure that the background is painted correct
558 	// on MacOS for example the background was gray and the image and other controls white
559 	SetFillColor(GetSettings().GetStyleSettings().GetWindowColor());
560 	SetLineColor();
561 	DrawRect(rRect);
562 
563 	DrawImage( maMainLogoPos, maMainLogo );
564 	DrawImage( maAppLogoPos, maAppLogo );
565 
566 	return;
567 }
568 
569 // -----------------------------------------------------------------------
570 
571 IMPL_LINK ( AboutDialog, OpenLinkHdl_Impl, svt::FixedHyperlink*, EMPTYARG )
572 {
573 	::rtl::OUString sURL( maCreditsLink.GetURL() );
574 	if ( sURL.getLength() > 0 )
575 	{
576 		try
577 		{
578 			uno::Reference< com::sun::star::system::XSystemShellExecute > xSystemShell(
579 				com::sun::star::system::SystemShellExecute::create(
580 					::comphelper::getProcessComponentContext() ) );
581 			if ( xSystemShell.is() )
582 				xSystemShell->execute( sURL, rtl::OUString(), com::sun::star::system::SystemShellExecuteFlags::DEFAULTS );
583 		}
584 		catch( const uno::Exception& e )
585 		{
586 			OSL_TRACE( "Caught exception: %s\n thread terminated.\n",
587 				rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
588 		}
589 	}
590 
591 	return 0;
592 }
593 
594 IMPL_LINK ( AboutDialog, ShowReadme_Impl, PushButton*, EMPTYARG )
595 {
596 	ReadmeDialog aDlg( this );
597 	aDlg.Execute();
598 
599 	return 0;
600 }
601 
602 /* vim: set noet sw=4 ts=4: */
603