1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <config_folders.h>
12 #include "personalization.hxx"
13 #include "personasdochandler.hxx"
15 #include <comphelper/processfactory.hxx>
16 #include <officecfg/Office/Common.hxx>
17 #include <com/sun/star/container/XNameAccess.hpp>
18 #include <com/sun/star/beans/XPropertySet.hpp>
19 #include <osl/file.hxx>
20 #include <rtl/bootstrap.hxx>
21 #include <rtl/strbuf.hxx>
22 #include <tools/urlobj.hxx>
23 #include <vcl/edit.hxx>
24 #include <vcl/msgbox.hxx>
25 #include <vcl/lstbox.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/settings.hxx>
28 #include <vcl/graphicfilter.hxx>
29 #include <dialmgr.hxx>
32 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
33 #include <com/sun/star/xml/sax/XParser.hpp>
34 #include <com/sun/star/xml/sax/Parser.hpp>
35 #include "ucbhelper/content.hxx"
37 using namespace com::sun::star
;
38 using namespace ::com::sun::star::uno
;
39 using namespace ::com::sun::star::ucb
;
40 using namespace ::com::sun::star::beans
;
42 SelectPersonaDialog::SelectPersonaDialog( vcl::Window
*pParent
)
43 : ModalDialog( pParent
, "SelectPersonaDialog", "cui/ui/select_persona_dialog.ui" )
45 get( m_pSearchButton
, "search_personas" );
46 m_pSearchButton
->SetClickHdl( LINK( this, SelectPersonaDialog
, SearchPersonas
) );
48 get( m_vSearchSuggestions
[0], "suggestion1" );
49 m_vSearchSuggestions
[0]->SetText( "LibreOffice" );
50 m_vSearchSuggestions
[0]->SetClickHdl( LINK( this, SelectPersonaDialog
, SearchPersonas
) );
52 get( m_vSearchSuggestions
[1], "suggestion2" );
53 m_vSearchSuggestions
[1]->SetText( CUI_RES ( RID_SVXSTR_PERSONA_ABSTRACT
) );
54 m_vSearchSuggestions
[1]->SetClickHdl( LINK( this, SelectPersonaDialog
, SearchPersonas
) );
56 get( m_vSearchSuggestions
[2], "suggestion3" );
57 m_vSearchSuggestions
[2]->SetText( CUI_RES ( RID_SVXSTR_PERSONA_COLOR
) );
58 m_vSearchSuggestions
[2]->SetClickHdl( LINK( this, SelectPersonaDialog
, SearchPersonas
) );
60 get( m_vSearchSuggestions
[3], "suggestion4" );
61 m_vSearchSuggestions
[3]->SetText( CUI_RES( RID_SVXSTR_PERSONA_MUSIC
) );
62 m_vSearchSuggestions
[3]->SetClickHdl( LINK( this, SelectPersonaDialog
, SearchPersonas
) );
64 get( m_vSearchSuggestions
[4], "suggestion5" );
65 m_vSearchSuggestions
[4]->SetText( CUI_RES( RID_SVXSTR_PERSONA_NATURE
) );
66 m_vSearchSuggestions
[4]->SetClickHdl( LINK( this, SelectPersonaDialog
, SearchPersonas
) );
68 get( m_pEdit
, "search_term" );
69 m_pEdit
->SetPlaceholderText( CUI_RES( RID_SVXSTR_SEARCHTERM
) );
71 get( m_pProgressLabel
, "progress_label" );
73 get( m_pOkButton
, "ok" );
74 m_pOkButton
->SetClickHdl( LINK( this, SelectPersonaDialog
, ActionOK
) );
76 get( m_pCancelButton
, "cancel" );
77 m_pCancelButton
->SetClickHdl( LINK( this, SelectPersonaDialog
, ActionCancel
) );
78 get( m_vResultList
[0], "result1" );
79 get( m_vResultList
[1], "result2" );
80 get( m_vResultList
[2], "result3" );
81 get( m_vResultList
[3], "result4" );
82 get( m_vResultList
[4], "result5" );
83 get( m_vResultList
[5], "result6" );
84 get( m_vResultList
[6], "result7" );
85 get( m_vResultList
[7], "result8" );
86 get( m_vResultList
[8], "result9" );
88 for (sal_Int32 nIndex
= 0; nIndex
< 9; ++nIndex
)
90 m_vResultList
[nIndex
]->SetClickHdl( LINK( this, SelectPersonaDialog
, SelectPersona
) );
91 m_vResultList
[nIndex
]->Disable();
95 SelectPersonaDialog::~SelectPersonaDialog()
100 void SelectPersonaDialog::dispose()
103 m_pSearchButton
.clear();
104 m_pProgressLabel
.clear();
105 for (VclPtr
<PushButton
> vp
: m_vResultList
)
107 for (VclPtr
<PushButton
> vp
: m_vSearchSuggestions
)
110 m_pCancelButton
.clear();
111 ModalDialog::dispose();
114 OUString
SelectPersonaDialog::GetSelectedPersona() const
116 if( !m_aSelectedPersona
.isEmpty( ) )
117 return m_aSelectedPersona
;
122 IMPL_LINK( SelectPersonaDialog
, SearchPersonas
, PushButton
*, pButton
)
125 if( m_rSearchThread
.is() )
126 m_rSearchThread
->StopExecution();
128 if( pButton
== m_pSearchButton
)
129 searchTerm
= m_pEdit
->GetText();
132 for( sal_Int32 nIndex
= 0; nIndex
< 5; nIndex
++ )
134 if( pButton
== m_vSearchSuggestions
[nIndex
] )
136 searchTerm
= m_vSearchSuggestions
[nIndex
]->GetDisplayText();
142 if( searchTerm
.isEmpty( ) )
146 // Before the release, the allizom.org url shoud be changed to:
147 // OUString rSearchURL = "https://services.addons.mozilla.org/en-US/firefox/api/1.5/search/" + searchTerm + "/9/9";
148 // The problem why it cannot be done just now is that the SSL negotiation
149 // with services.addons.mozilla.org fails very early - during an early
150 // propfind, SSL returns X509_V_ERR_CERT_UNTRUSTED to neon, causing the
151 // NE_SSL_UNTRUSTED being set in verify_callback in neon/src/ne_openssl.c
153 // This is not cleared anywhere during the init, and so later, even though
154 // we have found the certificate, this triggers
155 // NeonSession_CertificationNotify callback, that
156 // causes that NE_SSL_UNTRUSTED is igored in cases when the condition
157 // if ( pSession->isDomainMatch(
158 // GetHostnamePart( xEECert.get()->getSubjectName() ) ) )
159 // is true; but that is only when getSubjectName() actually returns a
160 // wildcard, or the exact name.
162 // In the case of services.addons.mozilla.com, the certificate is for
163 // versioncheck.addons.mozilla.com, but it also has
164 // X509v3 Subject Alternative Name:
165 // DNS:services.addons.mozilla.org, DNS:versioncheck-bg.addons.mozilla.org, DNS:pyrepo.addons.mozilla.org, DNS:versioncheck.addons.mozilla.org
166 // So it is all valid; but the early X509_V_ERR_CERT_UNTRUSTED failure
167 // described above just makes this being ignored.
169 // My suspicion is that this never actually worked, and the
170 // if ( pSession->isDomainMatch(
171 // GetHostnamePart( xEECert.get()->getSubjectName() ) ) )
172 // works around the root cause that is there for years, and which makes it
173 // work in most cases. I guess that we initialize something wrongly or
174 // too late; but I have already spent few hours debugging, and
175 // give up for the moment - need to return to this at some stage.
176 OUString rSearchURL
= "https://addons.allizom.org/en-US/firefox/api/1.5/search/" + searchTerm
+ "/9/9";
177 m_rSearchThread
= new SearchAndParseThread( this, rSearchURL
);
178 m_rSearchThread
->launch();
182 IMPL_LINK( SelectPersonaDialog
, ActionOK
, PushButton
*, /* pButton */ )
184 OUString aSelectedPersona
= GetSelectedPersona();
186 if( !aSelectedPersona
.isEmpty() )
188 m_rSearchThread
= new SearchAndParseThread( this, aSelectedPersona
);
189 m_rSearchThread
->launch();
194 if( m_rSearchThread
.is() )
195 m_rSearchThread
->StopExecution();
201 IMPL_LINK( SelectPersonaDialog
, ActionCancel
, PushButton
*, /* pButton */ )
203 if( m_rSearchThread
.is() )
204 m_rSearchThread
->StopExecution();
206 EndDialog( RET_CANCEL
);
210 IMPL_LINK( SelectPersonaDialog
, SelectPersona
, PushButton
*, pButton
)
212 if( m_rSearchThread
.is() )
213 m_rSearchThread
->StopExecution();
215 for( sal_Int32 index
= 0; index
< 9; index
++ )
217 if( pButton
== m_vResultList
[index
] )
219 if( !m_vPersonaSettings
[index
].isEmpty() )
221 m_aSelectedPersona
= m_vPersonaSettings
[index
];
222 // get the persona name from the setting variable to show in the progress.
223 sal_Int32 nNameIndex
= m_aSelectedPersona
.indexOf( ';' );
224 OUString aName
= m_aSelectedPersona
.copy( 0, nNameIndex
);
225 OUString
aProgress( CUI_RES( RID_SVXSTR_SELECTEDPERSONA
) );
227 SetProgress( aProgress
);
235 void SelectPersonaDialog::SetAppliedPersonaSetting( OUString
& rPersonaSetting
)
237 m_aAppliedPersona
= rPersonaSetting
;
240 OUString
SelectPersonaDialog::GetAppliedPersonaSetting() const
242 return m_aAppliedPersona
;
245 void SelectPersonaDialog::SetProgress( OUString
& rProgress
)
247 if(rProgress
.isEmpty())
248 m_pProgressLabel
->Hide();
251 SolarMutexGuard aGuard
;
252 m_pProgressLabel
->Show();
253 m_pProgressLabel
->SetText( rProgress
);
254 setOptimalLayoutSize();
258 void SelectPersonaDialog::SetImages( Image aImage
, sal_Int32 nIndex
)
260 m_vResultList
[nIndex
]->Enable();
261 m_vResultList
[nIndex
]->SetModeImage( aImage
);
264 void SelectPersonaDialog::AddPersonaSetting( OUString
& rPersonaSetting
)
266 m_vPersonaSettings
.push_back( rPersonaSetting
);
269 void SelectPersonaDialog::ClearSearchResults()
271 m_vPersonaSettings
.clear();
272 m_aSelectedPersona
.clear();
273 for( sal_Int32 nIndex
= 0; nIndex
< 9; nIndex
++ )
275 m_vResultList
[nIndex
]->Disable();
276 m_vResultList
[nIndex
]->SetModeImage(Image());
280 SvxPersonalizationTabPage::SvxPersonalizationTabPage( vcl::Window
*pParent
, const SfxItemSet
&rSet
)
281 : SfxTabPage( pParent
, "PersonalizationTabPage", "cui/ui/personalization_tab.ui", &rSet
)
284 get( m_pNoPersona
, "no_persona" );
285 get( m_pDefaultPersona
, "default_persona" );
287 get( m_pOwnPersona
, "own_persona" );
288 m_pOwnPersona
->SetClickHdl( LINK( this, SvxPersonalizationTabPage
, ForceSelect
) );
290 get( m_pSelectPersona
, "select_persona" );
291 m_pSelectPersona
->SetClickHdl( LINK( this, SvxPersonalizationTabPage
, SelectPersona
) );
293 get( m_vDefaultPersonaImages
[0], "default1" );
294 m_vDefaultPersonaImages
[0]->SetClickHdl( LINK( this, SvxPersonalizationTabPage
, DefaultPersona
) );
296 get( m_vDefaultPersonaImages
[1], "default2" );
297 m_vDefaultPersonaImages
[1]->SetClickHdl( LINK( this, SvxPersonalizationTabPage
, DefaultPersona
) );
299 get( m_vDefaultPersonaImages
[2], "default3" );
300 m_vDefaultPersonaImages
[2]->SetClickHdl( LINK( this, SvxPersonalizationTabPage
, DefaultPersona
) );
302 get( m_pPersonaList
, "installed_personas" );
303 m_pPersonaList
->SetSelectHdl( LINK( this, SvxPersonalizationTabPage
, SelectInstalledPersona
) );
305 get( m_pExtensionPersonaPreview
, "persona_preview" );
307 get ( m_pExtensionLabel
, "extensions_label" );
310 LoadExtensionThemes();
313 SvxPersonalizationTabPage::~SvxPersonalizationTabPage()
318 void SvxPersonalizationTabPage::dispose()
320 m_pNoPersona
.clear();
321 m_pDefaultPersona
.clear();
322 m_pOwnPersona
.clear();
323 m_pSelectPersona
.clear();
324 for (int i
=0; i
<3; ++i
)
325 m_vDefaultPersonaImages
[i
].clear();
326 m_pExtensionPersonaPreview
.clear();
327 m_pPersonaList
.clear();
328 m_pExtensionLabel
.clear();
329 SfxTabPage::dispose();
333 VclPtr
<SfxTabPage
> SvxPersonalizationTabPage::Create( vcl::Window
*pParent
, const SfxItemSet
*rSet
)
335 return VclPtr
<SvxPersonalizationTabPage
>::Create( pParent
, *rSet
);
338 bool SvxPersonalizationTabPage::FillItemSet( SfxItemSet
* )
341 OUString
aPersona( "default" );
342 if ( m_pNoPersona
->IsChecked() )
344 else if ( m_pOwnPersona
->IsChecked() )
347 bool bModified
= false;
348 uno::Reference
< uno::XComponentContext
> xContext( comphelper::getProcessComponentContext() );
349 if ( xContext
.is() &&
350 ( aPersona
!= officecfg::Office::Common::Misc::Persona::get( xContext
) ||
351 m_aPersonaSettings
!= officecfg::Office::Common::Misc::PersonaSettings::get( xContext
) ) )
357 std::shared_ptr
< comphelper::ConfigurationChanges
> batch( comphelper::ConfigurationChanges::create() );
358 if( aPersona
== "no" )
359 m_aPersonaSettings
.clear();
360 officecfg::Office::Common::Misc::Persona::set( aPersona
, batch
);
361 officecfg::Office::Common::Misc::PersonaSettings::set( m_aPersonaSettings
, batch
);
366 // broadcast the change
367 DataChangedEvent
aDataChanged( DataChangedEventType::SETTINGS
, NULL
, AllSettingsFlags::STYLE
);
368 Application::NotifyAllWindows( aDataChanged
);
374 void SvxPersonalizationTabPage::Reset( const SfxItemSet
* )
376 uno::Reference
< uno::XComponentContext
> xContext( comphelper::getProcessComponentContext() );
379 OUString
aPersona( "default" );
382 aPersona
= officecfg::Office::Common::Misc::Persona::get( xContext
);
383 m_aPersonaSettings
= officecfg::Office::Common::Misc::PersonaSettings::get( xContext
);
386 if ( aPersona
== "no" )
387 m_pNoPersona
->Check();
388 else if ( aPersona
== "own" )
389 m_pOwnPersona
->Check();
391 m_pDefaultPersona
->Check();
394 void SvxPersonalizationTabPage::SetPersonaSettings( const OUString
& aPersonaSettings
)
396 m_aPersonaSettings
= aPersonaSettings
;
397 m_pOwnPersona
->Check();
400 void SvxPersonalizationTabPage::LoadDefaultImages()
402 // Load the pre saved personas
404 OUString
gallery( "" );
405 gallery
= "$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER
;
406 gallery
+= "/gallery/personas/";
407 rtl::Bootstrap::expandMacros( gallery
);
408 OUString aPersonasList
= gallery
+ "personas_list.txt";
409 SvFileStream
aStream( aPersonasList
, StreamMode::READ
);
410 GraphicFilter aFilter
;
412 sal_Int32 nIndex
= 0;
414 while( aStream
.IsOpen() && !aStream
.IsEof() )
417 aStream
.ReadLine( aLine
);
418 OUString
aPersonaSetting( OStringToOUString( aLine
, RTL_TEXTENCODING_UTF8
) );
419 OUString aPreviewFile
;
420 sal_Int32 nNewIndex
= aPersonaSetting
.indexOf( ';', 0 );
423 aPreviewFile
= aPersonaSetting
.copy( 0, nNewIndex
);
424 aPersonaSetting
= aPersonaSetting
.copy( nNewIndex
+ 1 );
425 m_vDefaultPersonaSettings
.push_back( aPersonaSetting
);
427 INetURLObject
aURLObj( gallery
+ aPreviewFile
);
428 aFilter
.ImportGraphic( aGraphic
, aURLObj
);
429 Bitmap aBmp
= aGraphic
.GetBitmap();
430 m_vDefaultPersonaImages
[nIndex
]->Show();
431 m_vDefaultPersonaImages
[nIndex
++]->SetModeImage( Image( aBmp
) );
435 void SvxPersonalizationTabPage::LoadExtensionThemes()
437 // See if any extensions are used to install personas. If yes, load them.
439 css::uno::Sequence
<OUString
> installedPersonas( officecfg::Office::Common::Misc::PersonasList::get()->getElementNames() );
440 sal_Int32 nLength
= installedPersonas
.getLength();
445 m_pPersonaList
->Show();
446 m_pExtensionLabel
->Show();
448 for( sal_Int32 nIndex
= 0; nIndex
< nLength
; nIndex
++ )
450 Reference
< XPropertySet
> xPropertySet( officecfg::Office::Common::Misc::PersonasList::get()->getByName( installedPersonas
[nIndex
] ), UNO_QUERY_THROW
);
451 OUString aPersonaName
, aPreviewFile
, aHeaderFile
, aFooterFile
, aTextColor
, aAccentColor
, aPersonaSettings
;
452 Any aValue
= xPropertySet
->getPropertyValue( "Name" );
453 aValue
>>= aPersonaName
;
454 m_pPersonaList
->InsertEntry( aPersonaName
);
456 aValue
= xPropertySet
->getPropertyValue( "Preview" );
457 aValue
>>= aPreviewFile
;
459 aValue
= xPropertySet
->getPropertyValue( "Header" );
460 aValue
>>= aHeaderFile
;
462 aValue
= xPropertySet
->getPropertyValue( "Footer" );
463 aValue
>>= aFooterFile
;
465 aValue
= xPropertySet
->getPropertyValue( "TextColor" );
466 aValue
>>= aTextColor
;
468 aValue
= xPropertySet
->getPropertyValue( "AccentColor" );
469 aValue
>>= aAccentColor
;
471 aPersonaSettings
= aPreviewFile
+ ";" + aHeaderFile
+ ";" + aFooterFile
+ ";" + aTextColor
+ ";" + aAccentColor
;
472 rtl::Bootstrap::expandMacros( aPersonaSettings
);
473 m_vExtensionPersonaSettings
.push_back( aPersonaSettings
);
477 IMPL_LINK( SvxPersonalizationTabPage
, SelectPersona
, PushButton
*, /*pButton*/ )
479 ScopedVclPtrInstance
< SelectPersonaDialog
> aDialog(nullptr);
481 if ( aDialog
->Execute() == RET_OK
)
483 OUString
aPersonaSetting( aDialog
->GetAppliedPersonaSetting() );
484 if ( !aPersonaSetting
.isEmpty() )
486 SetPersonaSettings( aPersonaSetting
);
493 IMPL_LINK( SvxPersonalizationTabPage
, ForceSelect
, RadioButton
*, pButton
)
495 if ( pButton
== m_pOwnPersona
&& m_aPersonaSettings
.isEmpty() )
496 SelectPersona( m_pSelectPersona
);
501 IMPL_LINK( SvxPersonalizationTabPage
, DefaultPersona
, PushButton
*, pButton
)
503 m_pDefaultPersona
->Check();
504 for( sal_Int32 nIndex
= 0; nIndex
< 3; nIndex
++ )
506 if( pButton
== m_vDefaultPersonaImages
[nIndex
] )
507 m_aPersonaSettings
= m_vDefaultPersonaSettings
[nIndex
];
513 IMPL_LINK( SvxPersonalizationTabPage
, SelectInstalledPersona
, ListBox
*, )
515 m_pOwnPersona
->Check();
517 // Get the details of the selected theme.
518 m_pExtensionPersonaPreview
->Show();
519 sal_Int32 nSelectedPos
= m_pPersonaList
->GetSelectEntryPos();
520 OUString aSettings
= m_vExtensionPersonaSettings
[nSelectedPos
];
521 sal_Int32 nIndex
= aSettings
.indexOf( ';', 0 );
522 OUString aPreviewFile
= aSettings
.copy( 0, nIndex
);
523 m_aPersonaSettings
= aSettings
.copy( nIndex
+ 1 );
525 // Show the preview file in the button.
526 GraphicFilter aFilter
;
528 INetURLObject
aURLObj( aPreviewFile
);
529 aFilter
.ImportGraphic( aGraphic
, aURLObj
);
530 Bitmap aBmp
= aGraphic
.GetBitmap();
531 m_pExtensionPersonaPreview
->SetModeImage( Image( aBmp
) );
536 /// Find the value on the Persona page, and convert it to a usable form.
537 static OUString
searchValue( const OString
&rBuffer
, sal_Int32 from
, const OString
&rIdentifier
)
539 sal_Int32 where
= rBuffer
.indexOf( rIdentifier
, from
);
543 where
+= rIdentifier
.getLength();
545 sal_Int32 end
= rBuffer
.indexOf( """, where
);
549 OString
aOString( rBuffer
.copy( where
, end
- where
) );
550 OUString
aString( aOString
.getStr(), aOString
.getLength(), RTL_TEXTENCODING_UTF8
, OSTRING_TO_OUSTRING_CVTFLAGS
);
552 return aString
.replaceAll( "\\/", "/" );
555 /// Parse the Persona web page, and find where to get the bitmaps + the color values.
556 static bool parsePersonaInfo( const OString
&rBuffer
, OUString
*pHeaderURL
, OUString
*pFooterURL
,
557 OUString
*pTextColor
, OUString
*pAccentColor
, OUString
*pPreviewURL
,
560 // it is the first attribute that contains "persona="
561 sal_Int32 persona
= rBuffer
.indexOf( "data-browsertheme=\"{" );
566 *pHeaderURL
= searchValue( rBuffer
, persona
, ""headerURL":"" );
567 if ( pHeaderURL
->isEmpty() )
570 *pFooterURL
= searchValue( rBuffer
, persona
, ""footerURL":"" );
571 if ( pFooterURL
->isEmpty() )
574 *pTextColor
= searchValue( rBuffer
, persona
, ""textcolor":"" );
575 if ( pTextColor
->isEmpty() )
578 *pAccentColor
= searchValue( rBuffer
, persona
, ""accentcolor":"" );
579 if ( pAccentColor
->isEmpty() )
582 *pPreviewURL
= searchValue( rBuffer
, persona
, ""previewURL":"" );
583 if ( pPreviewURL
->isEmpty() )
586 *pName
= searchValue( rBuffer
, persona
, ""name":"" );
587 if ( pName
->isEmpty() )
593 SearchAndParseThread::SearchAndParseThread( SelectPersonaDialog
* pDialog
,
594 const OUString
& rURL
) :
595 Thread( "cuiPersonasSearchThread" ),
596 m_pPersonaDialog( pDialog
),
602 SearchAndParseThread::~SearchAndParseThread()
606 void SearchAndParseThread::execute()
608 if( m_aURL
.startsWith( "https://" ) )
610 m_pPersonaDialog
->ClearSearchResults();
611 OUString
sProgress( CUI_RES( RID_SVXSTR_SEARCHING
) );
612 m_pPersonaDialog
->SetProgress( sProgress
);
613 Reference
<XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
614 Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create(xContext
);
615 PersonasDocHandler
* pHandler
= new PersonasDocHandler();
616 Reference
< xml::sax::XDocumentHandler
> xDocHandler
= pHandler
;
617 uno::Reference
< ucb::XSimpleFileAccess3
> xFileAccess( ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ), uno::UNO_QUERY
);
618 uno::Reference
< io::XInputStream
> xStream
;
619 xParser
->setDocumentHandler( xDocHandler
);
621 if ( !xFileAccess
.is() )
625 xStream
= xFileAccess
->openFileRead( m_aURL
);
629 sProgress
= CUI_RES(RID_SVXSTR_SEARCHERROR
);
630 sProgress
= sProgress
.replaceAll("%1", m_aURL
);
631 m_pPersonaDialog
->SetProgress(sProgress
);
635 xml::sax::InputSource aParserInput
;
636 aParserInput
.aInputStream
= xStream
;
637 xParser
->parseStream( aParserInput
);
639 if( !pHandler
->hasResults() )
641 sProgress
= CUI_RES( RID_SVXSTR_NORESULTS
);
642 m_pPersonaDialog
->SetProgress( sProgress
);
646 std::vector
<OUString
> vLearnmoreURLs
= pHandler
->getLearnmoreURLs();
647 std::vector
<OUString
>::iterator it
;
648 sal_Int32 nIndex
= 0;
649 GraphicFilter aFilter
;
652 for( it
= vLearnmoreURLs
.begin(); it
!=vLearnmoreURLs
.end(); ++it
)
654 OUString sPreviewFile
, aPersonaSetting
;
655 getPreviewFile( *it
, &sPreviewFile
, &aPersonaSetting
);
656 INetURLObject
aURLObj( sPreviewFile
);
657 aFilter
.ImportGraphic( aGraphic
, aURLObj
);
658 Bitmap aBmp
= aGraphic
.GetBitmap();
663 // for VCL to be able to do visual changes in the thread
664 SolarMutexGuard aGuard
;
665 m_pPersonaDialog
->SetImages( Image( aBmp
), nIndex
++ );
666 m_pPersonaDialog
->setOptimalLayoutSize();
667 m_pPersonaDialog
->AddPersonaSetting( aPersonaSetting
);
673 SolarMutexGuard aGuard
;
675 m_pPersonaDialog
->SetProgress( sProgress
);
676 m_pPersonaDialog
->setOptimalLayoutSize();
681 OUString
sProgress( CUI_RES( RID_SVXSTR_APPLYPERSONA
) );
682 m_pPersonaDialog
->SetProgress( sProgress
);
684 uno::Reference
< ucb::XSimpleFileAccess3
> xFileAccess( ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ), uno::UNO_QUERY
);
685 if ( !xFileAccess
.is() )
688 OUString aName
, aHeaderURL
, aFooterURL
, aTextColor
, aAccentColor
;
689 OUString aPersonaSetting
;
691 // get the required fields from m_aURL
692 sal_Int32 nOldIndex
= 0;
693 sal_Int32 nNewIndex
= m_aURL
.indexOf( ';', nOldIndex
);
694 aName
= m_aURL
.copy( nOldIndex
, ( nNewIndex
- nOldIndex
) );
696 nOldIndex
= nNewIndex
+ 1;
697 nNewIndex
= m_aURL
.indexOf( ';', nOldIndex
);
698 aHeaderURL
= m_aURL
.copy(nOldIndex
, ( nNewIndex
- nOldIndex
) );
700 nOldIndex
= nNewIndex
+ 1;
701 nNewIndex
= m_aURL
.indexOf( ';', nOldIndex
);
702 aFooterURL
= m_aURL
.copy( nOldIndex
, ( nNewIndex
- nOldIndex
) );
704 nOldIndex
= nNewIndex
+ 1;
705 nNewIndex
= m_aURL
.indexOf( ';', nOldIndex
);
706 aTextColor
= m_aURL
.copy( nOldIndex
, ( nNewIndex
- nOldIndex
) );
708 nOldIndex
= nNewIndex
+ 1;
709 nNewIndex
= m_aURL
.getLength();
710 aAccentColor
= m_aURL
.copy( nOldIndex
, ( nNewIndex
- nOldIndex
) );
712 // copy the images to the user's gallery
713 OUString gallery
= "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE( "bootstrap") "::UserInstallation}";
714 rtl::Bootstrap::expandMacros( gallery
);
715 gallery
+= "/user/gallery/personas/";
716 osl::Directory::createPath( gallery
);
718 OUString
aHeaderFile( INetURLObject( aHeaderURL
).getName() );
719 OUString
aFooterFile( INetURLObject( aFooterURL
).getName() );
721 aHeaderFile
= aName
+ "/" + aHeaderFile
;
722 aFooterFile
= aName
+ "/" + aFooterFile
;
725 xFileAccess
->copy( aHeaderURL
, gallery
+ aHeaderFile
);
726 xFileAccess
->copy( aFooterURL
, gallery
+ aFooterFile
);
728 catch ( const uno::Exception
& )
730 sProgress
= CUI_RES( RID_SVXSTR_SEARCHERROR
);
731 sProgress
= sProgress
.replaceAll("%1", m_aURL
);
732 m_pPersonaDialog
->SetProgress( sProgress
);
739 SolarMutexGuard aGuard
;
741 aPersonaSetting
= aHeaderFile
+ ";" + aFooterFile
+ ";" + aTextColor
+ ";" + aAccentColor
;
742 m_pPersonaDialog
->SetAppliedPersonaSetting( aPersonaSetting
);
743 m_pPersonaDialog
->EndDialog( RET_OK
);
747 void SearchAndParseThread::getPreviewFile( const OUString
& rURL
, OUString
*pPreviewFile
, OUString
*pPersonaSetting
)
749 uno::Reference
< ucb::XSimpleFileAccess3
> xFileAccess( ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ), uno::UNO_QUERY
);
750 if ( !xFileAccess
.is() )
753 uno::Reference
< io::XInputStream
> xStream
;
755 xStream
= xFileAccess
->openFileRead( rURL
);
759 OUString
sProgress( CUI_RES( RID_SVXSTR_SEARCHERROR
) );
760 sProgress
= sProgress
.replaceAll("%1", m_aURL
);
761 m_pPersonaDialog
->SetProgress( sProgress
);
767 // read the persona specification
768 // NOTE: Parsing for real is an overkill here; and worse - I tried, and
769 // the HTML the site provides is not 100% valid ;-)
770 const sal_Int32 BUF_LEN
= 8000;
771 uno::Sequence
< sal_Int8
> buffer( BUF_LEN
);
772 OStringBuffer
aBuffer( 64000 );
775 while ( ( nRead
= xStream
->readBytes( buffer
, BUF_LEN
) ) == BUF_LEN
)
776 aBuffer
.append( reinterpret_cast< const char* >( buffer
.getConstArray() ), nRead
);
779 aBuffer
.append( reinterpret_cast< const char* >( buffer
.getConstArray() ), nRead
);
781 xStream
->closeInput();
783 // get the important bits of info
784 OUString aHeaderURL
, aFooterURL
, aTextColor
, aAccentColor
, aPreviewURL
, aName
;
786 if ( !parsePersonaInfo( aBuffer
.makeStringAndClear(), &aHeaderURL
, &aFooterURL
, &aTextColor
, &aAccentColor
, &aPreviewURL
, &aName
) )
789 // copy the images to the user's gallery
790 OUString gallery
= "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE( "bootstrap") "::UserInstallation}";
791 rtl::Bootstrap::expandMacros( gallery
);
792 gallery
+= "/user/gallery/personas/";
793 gallery
+= aName
+ "/";
794 osl::Directory::createPath( gallery
);
796 OUString
aPreviewFile( INetURLObject( aPreviewURL
).getName() );
799 xFileAccess
->copy( aPreviewURL
, gallery
+ aPreviewFile
);
801 catch ( const uno::Exception
& )
805 *pPreviewFile
= gallery
+ aPreviewFile
;
806 *pPersonaSetting
= aName
+ ";" + aHeaderURL
+ ";" + aFooterURL
+ ";" + aTextColor
+ ";" + aAccentColor
;
809 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */