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 
22 #include <sal/config.h>
23 
24 #include <algorithm>
25 #include <cassert>
26 
27 #include <vcl/errinf.hxx>
28 #include <ucbhelper/content.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/weld.hxx>
31 #include <avmedia/mediawindow.hxx>
32 #include <unotools/pathoptions.hxx>
33 #include <sfx2/opengrf.hxx>
34 #include <vcl/graphicfilter.hxx>
35 #include <svx/gallery1.hxx>
36 #include <svx/galtheme.hxx>
37 #include <cuigaldlg.hxx>
38 #include <bitmaps.hlst>
39 #include <unotools/localedatawrapper.hxx>
40 #include <unotools/syslocale.hxx>
41 #include <com/sun/star/uno/Reference.hxx>
42 #include <com/sun/star/lang/IllegalArgumentException.hpp>
43 #include <comphelper/processfactory.hxx>
44 #include <com/sun/star/sdbc/XResultSet.hpp>
45 #include <com/sun/star/sdbc/XRow.hpp>
46 #include <com/sun/star/ucb/ContentCreationException.hpp>
47 #include <com/sun/star/ucb/XContentAccess.hpp>
48 #include <com/sun/star/ui/dialogs/FolderPicker.hpp>
49 #include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
50 #include <dialmgr.hxx>
51 #include <strings.hrc>
52 #include <svx/dialmgr.hxx>
53 #include <svx/strings.hrc>
54 
55 using namespace ::ucbhelper;
56 using namespace ::cppu;
57 using namespace ::com::sun::star::lang;
58 using namespace ::com::sun::star::sdbc;
59 using namespace ::com::sun::star::ucb;
60 using namespace ::com::sun::star::ui::dialogs;
61 using namespace ::com::sun::star::uno;
62 
63 
SearchThread(SearchProgress * pProgress,TPGalleryThemeProperties * pBrowser,const INetURLObject & rStartURL)64 SearchThread::SearchThread(SearchProgress* pProgress,
65                            TPGalleryThemeProperties* pBrowser,
66                            const INetURLObject& rStartURL)
67     : Thread("cuiSearchThread")
68     , mpProgress(pProgress)
69     , mpBrowser(pBrowser)
70     , maStartURL(rStartURL)
71 {
72 }
73 
~SearchThread()74 SearchThread::~SearchThread()
75 {
76 }
77 
execute()78 void SearchThread::execute()
79 {
80     const OUString aFileType(mpBrowser->m_xCbbFileType->get_active_text());
81 
82     if (!aFileType.isEmpty())
83     {
84         const int nFileNumber = mpBrowser->m_xCbbFileType->find_text(aFileType);
85         sal_Int32 nBeginFormat, nEndFormat;
86         std::vector< OUString > aFormats;
87 
88         if( !nFileNumber || nFileNumber == -1)
89         {
90             nBeginFormat = 1;
91             nEndFormat = mpBrowser->m_xCbbFileType->get_count() - 1;
92         }
93         else
94             nBeginFormat = nEndFormat = nFileNumber;
95 
96         for (sal_Int32 i = nBeginFormat; i <= nEndFormat; ++i)
97             aFormats.push_back( mpBrowser->aFilterEntryList[ i ]->aFilterName.toAsciiLowerCase() );
98 
99         ImplSearch( maStartURL, aFormats, mpBrowser->bSearchRecursive );
100     }
101 
102     Application::PostUserEvent(LINK(mpProgress, SearchProgress, CleanUpHdl));
103 }
104 
105 
ImplSearch(const INetURLObject & rStartURL,const std::vector<OUString> & rFormats,bool bRecursive)106 void SearchThread::ImplSearch( const INetURLObject& rStartURL,
107                                const std::vector< OUString >& rFormats,
108                                bool bRecursive )
109 {
110     {
111         SolarMutexGuard aGuard;
112 
113         mpProgress->SetDirectory( rStartURL );
114     }
115 
116     try
117     {
118         css::uno::Reference< XCommandEnvironment > xEnv;
119         Content aCnt( rStartURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xEnv, comphelper::getProcessComponentContext() );
120         Sequence< OUString > aProps( 2 );
121 
122         aProps.getArray()[ 0 ] = "IsFolder";
123         aProps.getArray()[ 1 ] = "IsDocument";
124         css::uno::Reference< XResultSet > xResultSet(
125             aCnt.createCursor( aProps ) );
126 
127         if( xResultSet.is() )
128         {
129             css::uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW );
130             css::uno::Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW );
131 
132             while( xResultSet->next() && schedule() )
133             {
134                 INetURLObject   aFoundURL( xContentAccess->queryContentIdentifierString() );
135                 DBG_ASSERT( aFoundURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" );
136 
137                 bool bFolder = xRow->getBoolean( 1 ); // property "IsFolder"
138                 if ( xRow->wasNull() )
139                     bFolder = false;
140 
141                 if( bRecursive && bFolder )
142                     ImplSearch( aFoundURL, rFormats, true );
143                 else
144                 {
145                     bool bDocument = xRow->getBoolean( 2 ); // property "IsDocument"
146                     if ( xRow->wasNull() )
147                         bDocument = false;
148 
149                     if( bDocument )
150                     {
151                         GraphicDescriptor   aDesc( aFoundURL );
152 
153                         if( ( aDesc.Detect() &&
154                               std::find( rFormats.begin(),
155                                            rFormats.end(),
156                                            GraphicDescriptor::GetImportFormatShortName(
157                                                aDesc.GetFileFormat() ).toAsciiLowerCase() )
158                               != rFormats.end() ) ||
159                             std::find( rFormats.begin(),
160                                          rFormats.end(),
161                                          aFoundURL.GetFileExtension().toAsciiLowerCase())
162                             != rFormats.end() )
163                         {
164                             SolarMutexGuard aGuard;
165 
166                             mpBrowser->aFoundList.push_back(
167                                 aFoundURL.GetMainURL( INetURLObject::DecodeMechanism::NONE )
168                             );
169                             mpBrowser->m_xLbxFound->insert_text(
170                                 mpBrowser->aFoundList.size() - 1,
171                                 GetReducedString(aFoundURL, 50));
172                         }
173                     }
174                 }
175             }
176         }
177     }
178     catch (const ContentCreationException&)
179     {
180     }
181     catch (const css::uno::RuntimeException&)
182     {
183     }
184     catch (const css::uno::Exception&)
185     {
186     }
187 }
188 
SearchProgress(weld::Window * pParent,TPGalleryThemeProperties * pTabPage,const INetURLObject & rStartURL)189 SearchProgress::SearchProgress(weld::Window* pParent, TPGalleryThemeProperties* pTabPage, const INetURLObject& rStartURL)
190     : GenericDialogController(pParent, "cui/ui/gallerysearchprogress.ui", "GallerySearchProgress")
191     , startUrl_(rStartURL)
192     , m_pTabPage(pTabPage)
193     , m_xFtSearchDir(m_xBuilder->weld_label("dir"))
194     , m_xFtSearchType(m_xBuilder->weld_label("file"))
195     , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
196 {
197     m_xFtSearchType->set_size_request(m_xFtSearchType->get_preferred_size().Width(), -1);
198     m_xBtnCancel->connect_clicked(LINK(this, SearchProgress, ClickCancelBtn));
199 }
200 
~SearchProgress()201 SearchProgress::~SearchProgress()
202 {
203 }
204 
IMPL_LINK_NOARG(SearchProgress,ClickCancelBtn,weld::Button &,void)205 IMPL_LINK_NOARG(SearchProgress, ClickCancelBtn, weld::Button&, void)
206 {
207     if (m_aSearchThread.is())
208         m_aSearchThread->terminate();
209 }
210 
IMPL_LINK_NOARG(SearchProgress,CleanUpHdl,void *,void)211 IMPL_LINK_NOARG(SearchProgress, CleanUpHdl, void*, void)
212 {
213     if (m_aSearchThread.is())
214         m_aSearchThread->join();
215 
216     m_xDialog->response(RET_OK);
217 }
218 
LaunchThread()219 void SearchProgress::LaunchThread()
220 {
221     assert(!m_aSearchThread.is());
222     m_aSearchThread = new SearchThread(this, m_pTabPage, startUrl_);
223     m_aSearchThread->launch();
224 }
225 
TakeThread(TakeProgress * pProgress,TPGalleryThemeProperties * pBrowser,TokenList_impl & rTakenList)226 TakeThread::TakeThread(
227     TakeProgress* pProgress,
228     TPGalleryThemeProperties* pBrowser,
229     TokenList_impl& rTakenList
230 ) :
231     Thread      ( "cuiTakeThread" ),
232     mpProgress  ( pProgress ),
233     mpBrowser   ( pBrowser ),
234     mrTakenList ( rTakenList )
235 {
236 }
237 
238 
~TakeThread()239 TakeThread::~TakeThread()
240 {
241 }
242 
execute()243 void TakeThread::execute()
244 {
245     sal_Int32           nEntries;
246     GalleryTheme*       pThm = mpBrowser->GetXChgData()->pTheme;
247     std::unique_ptr<GalleryProgress> pStatusProgress;
248 
249     std::vector<int> aSelectedRows;
250 
251     {
252         SolarMutexGuard aGuard;
253         pStatusProgress.reset(new GalleryProgress);
254         if (mpBrowser->bTakeAll)
255             nEntries = mpBrowser->m_xLbxFound->n_children();
256         else
257         {
258             aSelectedRows = mpBrowser->m_xLbxFound->get_selected_rows();
259             nEntries = aSelectedRows.size();
260         }
261         pThm->LockBroadcaster();
262     }
263 
264     for( sal_Int32 i = 0; i < nEntries && schedule(); ++i )
265     {
266         const sal_Int32 nPos = mpBrowser->bTakeAll ? i : aSelectedRows[i];
267         const INetURLObject aURL( mpBrowser->aFoundList[ nPos ]);
268 
269         mrTakenList.push_back( static_cast<sal_uLong>(nPos) );
270 
271         {
272             SolarMutexGuard aGuard;
273 
274             mpProgress->SetFile( aURL );
275             pStatusProgress->Update( i, nEntries - 1 );
276             pThm->InsertURL( aURL );
277         }
278     }
279 
280     {
281         SolarMutexGuard aGuard;
282 
283         pThm->UnlockBroadcaster();
284         pStatusProgress.reset();
285     }
286 
287     Application::PostUserEvent(LINK(mpProgress, TakeProgress, CleanUpHdl));
288 }
289 
TakeProgress(weld::Window * pParent,TPGalleryThemeProperties * pTabPage)290 TakeProgress::TakeProgress(weld::Window* pParent, TPGalleryThemeProperties* pTabPage)
291     : GenericDialogController(pParent, "cui/ui/galleryapplyprogress.ui",
292                               "GalleryApplyProgress")
293     , m_pParent(pParent)
294     , m_pTabPage(pTabPage)
295     , m_xFtTakeFile(m_xBuilder->weld_label("file"))
296     , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
297 {
298     m_xBtnCancel->connect_clicked(LINK(this, TakeProgress, ClickCancelBtn));
299 }
300 
~TakeProgress()301 TakeProgress::~TakeProgress()
302 {
303 }
304 
IMPL_LINK_NOARG(TakeProgress,ClickCancelBtn,weld::Button &,void)305 IMPL_LINK_NOARG(TakeProgress, ClickCancelBtn, weld::Button&, void)
306 {
307     if (maTakeThread.is())
308         maTakeThread->terminate();
309 }
310 
311 
IMPL_LINK_NOARG(TakeProgress,CleanUpHdl,void *,void)312 IMPL_LINK_NOARG(TakeProgress, CleanUpHdl, void*, void)
313 {
314     if (maTakeThread.is())
315         maTakeThread->join();
316 
317     std::vector<bool, std::allocator<bool> > aRemoveEntries(m_pTabPage->aFoundList.size(), false);
318     std::vector< OUString >   aRemainingVector;
319     sal_uInt32                  i, nCount;
320 
321     std::unique_ptr<weld::WaitObject> xWait(new weld::WaitObject(m_pParent));
322 
323     m_pTabPage->m_xLbxFound->select(-1);
324     m_pTabPage->m_xLbxFound->freeze();
325 
326     // mark all taken positions in aRemoveEntries
327     for( i = 0, nCount = maTakenList.size(); i < nCount; ++i )
328         aRemoveEntries[ maTakenList[ i ] ] = true;
329     maTakenList.clear();
330 
331     // refill found list
332     for( i = 0, nCount = aRemoveEntries.size(); i < nCount; ++i )
333         if( !aRemoveEntries[ i ] )
334             aRemainingVector.push_back( m_pTabPage->aFoundList[i] );
335 
336     m_pTabPage->aFoundList.clear();
337 
338     for( i = 0, nCount = aRemainingVector.size(); i < nCount; ++i )
339         m_pTabPage->aFoundList.push_back( aRemainingVector[ i ] );
340 
341     aRemainingVector.clear();
342 
343     // refill list box
344     for( i = 0, nCount = aRemoveEntries.size(); i < nCount; ++i )
345         if( !aRemoveEntries[ i ] )
346             aRemainingVector.push_back(m_pTabPage->m_xLbxFound->get_text(i));
347 
348     m_pTabPage->m_xLbxFound->clear();
349 
350     for( i = 0, nCount = aRemainingVector.size(); i < nCount; ++i )
351         m_pTabPage->m_xLbxFound->append_text(aRemainingVector[i]);
352 
353     aRemainingVector.clear();
354 
355     m_pTabPage->m_xLbxFound->thaw();
356     m_pTabPage->SelectFoundHdl( *m_pTabPage->m_xLbxFound );
357 
358     xWait.reset();
359 
360     m_xDialog->response(RET_OK);
361 }
362 
LaunchThread()363 void TakeProgress::LaunchThread()
364 {
365     assert(!maTakeThread.is());
366     maTakeThread = new TakeThread(this, m_pTabPage, maTakenList);
367     maTakeThread->launch();
368 }
369 
ActualizeProgress(weld::Window * pWindow,GalleryTheme * pThm)370 ActualizeProgress::ActualizeProgress(weld::Window* pWindow, GalleryTheme* pThm)
371     : GenericDialogController(pWindow, "cui/ui/galleryupdateprogress.ui",
372                               "GalleryUpdateProgress")
373     , pIdle(nullptr)
374     , pTheme(pThm)
375     , m_xFtActualizeFile(m_xBuilder->weld_label("file"))
376     , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
377 {
378     m_xBtnCancel->connect_clicked(LINK(this, ActualizeProgress, ClickCancelBtn));
379 }
380 
~ActualizeProgress()381 ActualizeProgress::~ActualizeProgress()
382 {
383 }
384 
run()385 short ActualizeProgress::run()
386 {
387     pIdle = new Idle("ActualizeProgressTimeout");
388     pIdle->SetInvokeHandler( LINK( this, ActualizeProgress, TimeoutHdl ) );
389     pIdle->SetPriority( TaskPriority::LOWEST );
390     pIdle->Start();
391 
392     return GenericDialogController::run();
393 }
394 
IMPL_LINK_NOARG(ActualizeProgress,ClickCancelBtn,weld::Button &,void)395 IMPL_LINK_NOARG(ActualizeProgress, ClickCancelBtn, weld::Button&, void)
396 {
397     pTheme->AbortActualize();
398     m_xDialog->response(RET_OK);
399 }
400 
IMPL_LINK(ActualizeProgress,TimeoutHdl,Timer *,_pTimer,void)401 IMPL_LINK( ActualizeProgress, TimeoutHdl, Timer*, _pTimer, void)
402 {
403     if (_pTimer)
404     {
405         _pTimer->Stop();
406         delete _pTimer;
407     }
408 
409     pTheme->Actualize(LINK(this, ActualizeProgress, ActualizeHdl), &aStatusProgress);
410     ClickCancelBtn(*m_xBtnCancel);
411 }
412 
IMPL_LINK(ActualizeProgress,ActualizeHdl,const INetURLObject &,rURL,void)413 IMPL_LINK( ActualizeProgress, ActualizeHdl, const INetURLObject&, rURL, void )
414 {
415     Application::Reschedule(true);
416     m_xFtActualizeFile->set_label(GetReducedString(rURL, 30));
417 }
418 
TitleDialog(weld::Window * pParent,const OUString & rOldTitle)419 TitleDialog::TitleDialog(weld::Window* pParent, const OUString& rOldTitle)
420     : GenericDialogController(pParent, "cui/ui/gallerytitledialog.ui", "GalleryTitleDialog")
421     , m_xEdit(m_xBuilder->weld_entry("entry"))
422 {
423     m_xEdit->set_text(rOldTitle);
424     m_xEdit->grab_focus();
425 }
426 
~TitleDialog()427 TitleDialog::~TitleDialog()
428 {
429 }
430 
GalleryIdDialog(weld::Window * pParent,GalleryTheme * _pThm)431 GalleryIdDialog::GalleryIdDialog(weld::Window* pParent, GalleryTheme* _pThm)
432     : GenericDialogController(pParent, "cui/ui/gallerythemeiddialog.ui", "GalleryThemeIDDialog")
433     , m_pThm(_pThm)
434     , m_xBtnOk(m_xBuilder->weld_button("ok"))
435     , m_xLbResName(m_xBuilder->weld_combo_box("entry"))
436 {
437     m_xLbResName->append_text("!!! No Id !!!");
438 
439     GalleryTheme::InsertAllThemes(*m_xLbResName);
440 
441     m_xLbResName->set_active(m_pThm->GetId());
442     m_xLbResName->grab_focus();
443 
444     m_xBtnOk->connect_clicked(LINK(this, GalleryIdDialog, ClickOkHdl));
445 }
446 
~GalleryIdDialog()447 GalleryIdDialog::~GalleryIdDialog()
448 {
449 }
450 
IMPL_LINK_NOARG(GalleryIdDialog,ClickOkHdl,weld::Button &,void)451 IMPL_LINK_NOARG(GalleryIdDialog, ClickOkHdl, weld::Button&, void)
452 {
453     Gallery*    pGal = m_pThm->GetParent();
454     const sal_uLong nId = GetId();
455     bool        bDifferentThemeExists = false;
456 
457     for( sal_uLong i = 0, nCount = pGal->GetThemeCount(); i < nCount && !bDifferentThemeExists; i++ )
458     {
459         const GalleryThemeEntry* pInfo = pGal->GetThemeInfo( i );
460 
461         if ((pInfo->GetId() == nId) && (pInfo->GetThemeName() != m_pThm->GetName()))
462         {
463             OUString aStr = CuiResId( RID_SVXSTR_GALLERY_ID_EXISTS ) +
464                 " (" + pInfo->GetThemeName() + ")";
465 
466             std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
467                                                           VclMessageType::Info, VclButtonsType::Ok,
468                                                           aStr));
469             xInfoBox->run();
470             m_xLbResName->grab_focus();
471             bDifferentThemeExists = true;
472         }
473     }
474 
475     if (!bDifferentThemeExists)
476         m_xDialog->response(RET_OK);
477 }
478 
GalleryThemeProperties(weld::Window * pParent,ExchangeData * _pData,SfxItemSet const * pItemSet)479 GalleryThemeProperties::GalleryThemeProperties(weld::Window* pParent,
480     ExchangeData* _pData, SfxItemSet const * pItemSet)
481     : SfxTabDialogController(pParent, "cui/ui/gallerythemedialog.ui",
482                              "GalleryThemeDialog", pItemSet)
483     , pData(_pData)
484 {
485     AddTabPage("general", TPGalleryThemeGeneral::Create, nullptr);
486     AddTabPage("files", TPGalleryThemeProperties::Create, nullptr);
487     if (pData->pTheme->IsReadOnly())
488         RemoveTabPage("files");
489 
490     OUString aText = m_xDialog->get_title().replaceFirst( "%1",  pData->pTheme->GetName() );
491 
492     if (pData->pTheme->IsReadOnly())
493         aText +=  " " + CuiResId( RID_SVXSTR_GALLERY_READONLY );
494 
495     m_xDialog->set_title(aText);
496 }
497 
PageCreated(const OString & rId,SfxTabPage & rPage)498 void GalleryThemeProperties::PageCreated(const OString& rId, SfxTabPage &rPage)
499 {
500     if (rId == "general")
501         static_cast<TPGalleryThemeGeneral&>( rPage ).SetXChgData( pData );
502     else
503         static_cast<TPGalleryThemeProperties&>( rPage ).SetXChgData( pData );
504 }
505 
TPGalleryThemeGeneral(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)506 TPGalleryThemeGeneral::TPGalleryThemeGeneral(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
507     : SfxTabPage(pPage, pController, "cui/ui/gallerygeneralpage.ui", "GalleryGeneralPage", &rSet)
508     , pData(nullptr)
509     , m_xFiMSImage(m_xBuilder->weld_image("image"))
510     , m_xEdtMSName(m_xBuilder->weld_entry("name"))
511     , m_xFtMSShowType(m_xBuilder->weld_label("type"))
512     , m_xFtMSShowPath(m_xBuilder->weld_label("location"))
513     , m_xFtMSShowContent(m_xBuilder->weld_label("contents"))
514     , m_xFtMSShowChangeDate(m_xBuilder->weld_label("modified"))
515 {
516 }
517 
SetXChgData(ExchangeData * _pData)518 void TPGalleryThemeGeneral::SetXChgData( ExchangeData* _pData )
519 {
520     pData = _pData;
521 
522     GalleryTheme*       pThm = pData->pTheme;
523     OUString            aOutStr( OUString::number(pThm->GetObjectCount()) );
524     OUString            aObjStr( CuiResId( RID_SVXSTR_GALLERYPROPS_OBJECT ) );
525     OUString            aAccess;
526     OUString            aType( SvxResId( RID_SVXSTR_GALLERYPROPS_GALTHEME ) );
527     bool            bReadOnly = pThm->IsReadOnly();
528 
529     m_xEdtMSName->set_text(pThm->GetName());
530     m_xEdtMSName->set_editable(!bReadOnly);
531     m_xEdtMSName->set_sensitive(!bReadOnly);
532 
533     if( pThm->IsReadOnly() )
534         aType += CuiResId( RID_SVXSTR_GALLERY_READONLY );
535 
536     m_xFtMSShowType->set_label(aType);
537     m_xFtMSShowPath->set_label(pThm->GetSdgURL().GetMainURL(INetURLObject::DecodeMechanism::Unambiguous));
538 
539     // singular or plural?
540     if ( 1 == pThm->GetObjectCount() )
541         aObjStr = aObjStr.getToken( 0, ';' );
542     else
543         aObjStr = aObjStr.getToken( 1, ';' );
544 
545     aOutStr += " " + aObjStr;
546 
547     m_xFtMSShowContent->set_label(aOutStr);
548 
549     // get locale wrapper (singleton)
550     const SvtSysLocale aSysLocale;
551     const LocaleDataWrapper&    aLocaleData = aSysLocale.GetLocaleData();
552 
553     // ChangeDate/Time
554     aAccess = aLocaleData.getDate( pData->aThemeChangeDate ) + ", " + aLocaleData.getTime( pData->aThemeChangeTime );
555     m_xFtMSShowChangeDate->set_label(aAccess);
556 
557     // set image
558     OUString sId;
559 
560     if( pThm->IsReadOnly() )
561         sId = RID_SVXBMP_THEME_READONLY_BIG;
562     else if( pThm->IsDefault() )
563         sId = RID_SVXBMP_THEME_DEFAULT_BIG;
564     else
565         sId = RID_SVXBMP_THEME_NORMAL_BIG;
566 
567     m_xFiMSImage->set_from_icon_name(sId);
568 }
569 
FillItemSet(SfxItemSet *)570 bool TPGalleryThemeGeneral::FillItemSet( SfxItemSet* /*rSet*/ )
571 {
572     pData->aEditedTitle = m_xEdtMSName->get_text();
573     return true;
574 }
575 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)576 std::unique_ptr<SfxTabPage> TPGalleryThemeGeneral::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
577 {
578     return std::make_unique<TPGalleryThemeGeneral>(pPage, pController, *rSet);
579 }
580 
TPGalleryThemeProperties(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)581 TPGalleryThemeProperties::TPGalleryThemeProperties(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
582     : SfxTabPage(pPage, pController, "cui/ui/galleryfilespage.ui", "GalleryFilesPage", &rSet)
583     , pData(nullptr)
584     , bEntriesFound(false)
585     , bInputAllowed(true)
586     , bTakeAll(false)
587     , bSearchRecursive(false)
588     , xDialogListener(new ::svt::DialogClosedListener())
589     , m_xCbbFileType(m_xBuilder->weld_combo_box("filetype"))
590     , m_xLbxFound(m_xBuilder->weld_tree_view("files"))
591     , m_xBtnSearch(m_xBuilder->weld_button("findfiles"))
592     , m_xBtnTake(m_xBuilder->weld_button("add"))
593     , m_xBtnTakeAll(m_xBuilder->weld_button("addall"))
594     , m_xCbxPreview(m_xBuilder->weld_check_button("preview"))
595     , m_xWndPreview(new weld::CustomWeld(*m_xBuilder, "image", m_aWndPreview))
596 {
597     m_xLbxFound->set_size_request(m_xLbxFound->get_approximate_digit_width() * 35,
598                                   m_xLbxFound->get_height_rows(15));
599     m_xLbxFound->set_selection_mode(SelectionMode::Multiple);
600     xDialogListener->SetDialogClosedLink( LINK( this, TPGalleryThemeProperties, DialogClosedHdl ) );
601 }
602 
SetXChgData(ExchangeData * _pData)603 void TPGalleryThemeProperties::SetXChgData( ExchangeData* _pData )
604 {
605     pData = _pData;
606 
607     aPreviewTimer.SetInvokeHandler( LINK( this, TPGalleryThemeProperties, PreviewTimerHdl ) );
608     aPreviewTimer.SetTimeout( 500 );
609     m_xBtnSearch->connect_clicked(LINK(this, TPGalleryThemeProperties, ClickSearchHdl));
610     m_xBtnTake->connect_clicked(LINK(this, TPGalleryThemeProperties, ClickTakeHdl));
611     m_xBtnTakeAll->connect_clicked(LINK(this, TPGalleryThemeProperties, ClickTakeAllHdl));
612     m_xCbxPreview->connect_toggled(LINK(this, TPGalleryThemeProperties, ClickPreviewHdl));
613     m_xCbbFileType->connect_changed(LINK(this, TPGalleryThemeProperties, SelectFileTypeHdl));
614     m_xLbxFound->connect_row_activated(LINK(this, TPGalleryThemeProperties, DClickFoundHdl));
615     m_xLbxFound->connect_changed(LINK(this, TPGalleryThemeProperties, SelectFoundHdl));
616     m_xLbxFound->append_text(CuiResId(RID_SVXSTR_GALLERY_NOFILES));
617     m_xLbxFound->show();
618 
619     FillFilterList();
620 
621     m_xBtnTake->set_sensitive(true);
622     m_xBtnTakeAll->set_sensitive(false);
623     m_xCbxPreview->set_sensitive(false);
624 }
625 
StartSearchFiles(const OUString & _rFolderURL,short _nDlgResult)626 void TPGalleryThemeProperties::StartSearchFiles( const OUString& _rFolderURL, short _nDlgResult )
627 {
628     if ( RET_OK == _nDlgResult )
629     {
630         aURL = INetURLObject( _rFolderURL );
631         bSearchRecursive = true;    // UI choice no longer possible, windows file picker allows no user controls
632         SearchFiles();
633     }
634 }
635 
~TPGalleryThemeProperties()636 TPGalleryThemeProperties::~TPGalleryThemeProperties()
637 {
638     xMediaPlayer.clear();
639     xDialogListener.clear();
640     aFilterEntryList.clear();
641 }
642 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)643 std::unique_ptr<SfxTabPage> TPGalleryThemeProperties::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
644 {
645     return std::make_unique<TPGalleryThemeProperties>(pPage, pController, *rSet);
646 }
647 
addExtension(const OUString & _rDisplayText,const OUString & _rExtension)648 OUString TPGalleryThemeProperties::addExtension( const OUString& _rDisplayText, const OUString& _rExtension )
649 {
650     OUString sRet = _rDisplayText;
651     if ( sRet.indexOf( "(*.*)" ) == -1 )
652     {
653         sRet += " (" + _rExtension + ")";
654     }
655     return sRet;
656 }
657 
FillFilterList()658 void TPGalleryThemeProperties::FillFilterList()
659 {
660     GraphicFilter &rFilter = GraphicFilter::GetGraphicFilter();
661     OUString            aExt;
662     OUString            aName;
663     sal_uInt16          i, nKeyCount;
664 
665     // graphic filters
666     for( i = 0, nKeyCount = rFilter.GetImportFormatCount(); i < nKeyCount; i++ )
667     {
668         aExt = rFilter.GetImportFormatShortName( i );
669         aName = rFilter.GetImportFormatName( i );
670         size_t entryIndex = 0;
671         FilterEntry* pTestEntry = aFilterEntryList.empty() ? nullptr : aFilterEntryList[ entryIndex ].get();
672         bool bInList = false;
673 
674         OUString aExtensions;
675         int j = 0;
676         OUString sWildcard;
677         while( true )
678         {
679             sWildcard = rFilter.GetImportWildcard( i, j++ );
680             if ( sWildcard.isEmpty() )
681                 break;
682             if ( aExtensions.indexOf( sWildcard ) == -1 )
683             {
684                 if ( !aExtensions.isEmpty() )
685                     aExtensions += ";";
686                 aExtensions += sWildcard;
687             }
688         }
689         aName = addExtension( aName, aExtensions );
690 
691         while( pTestEntry )
692         {
693             if ( pTestEntry->aFilterName == aExt )
694             {
695                 bInList = true;
696                 break;
697             }
698             pTestEntry = ( ++entryIndex < aFilterEntryList.size() )
699                        ? aFilterEntryList[ entryIndex ].get() : nullptr;
700         }
701         if ( !bInList )
702         {
703             std::unique_ptr<FilterEntry> pFilterEntry(new FilterEntry);
704             pFilterEntry->aFilterName = aExt;
705             m_xCbbFileType->append_text(aName);
706             aFilterEntryList.push_back(std::move(pFilterEntry));
707         }
708     }
709 
710 #if HAVE_FEATURE_AVMEDIA
711     // media filters
712     static const char aWildcard[] = "*.";
713     ::avmedia::FilterNameVector     aFilters= ::avmedia::MediaWindow::getMediaFilters();
714 
715     for(const std::pair<OUString,OUString> & aFilter : aFilters)
716     {
717         for( sal_Int32 nIndex = 0; nIndex >= 0; )
718         {
719             OUString aFilterWildcard( aWildcard );
720 
721             std::unique_ptr<FilterEntry> pFilterEntry(new FilterEntry);
722             pFilterEntry->aFilterName = aFilter.second.getToken( 0, ';', nIndex );
723             aFilterWildcard += pFilterEntry->aFilterName;
724             m_xCbbFileType->append_text(addExtension(aFilter.first, aFilterWildcard));
725             aFilterEntryList.push_back( std::move(pFilterEntry) );
726         }
727     }
728 #endif
729 
730     // 'All' filters
731     OUString aExtensions;
732 
733     // graphic filters
734     for ( i = 0; i < nKeyCount; ++i )
735     {
736         int j = 0;
737         OUString sWildcard;
738         while( true )
739         {
740             sWildcard = rFilter.GetImportWildcard( i, j++ );
741             if ( sWildcard.isEmpty() )
742                 break;
743             if ( aExtensions.indexOf( sWildcard ) == -1 )
744             {
745                 if ( !aExtensions.isEmpty() )
746                     aExtensions += ";";
747 
748                 aExtensions += sWildcard;
749             }
750         }
751     }
752 
753 #if HAVE_FEATURE_AVMEDIA
754     // media filters
755     for(const std::pair<OUString,OUString> & aFilter : aFilters)
756     {
757         for( sal_Int32 nIndex = 0; nIndex >= 0; )
758         {
759             if ( !aExtensions.isEmpty() )
760                 aExtensions += ";";
761             aExtensions += aWildcard + aFilter.second.getToken( 0, ';', nIndex );
762         }
763      }
764 #endif
765 
766 #if defined(_WIN32)
767     if (aExtensions.getLength() > 240)
768         aExtensions = "*.*";
769 #endif
770 
771     std::unique_ptr<FilterEntry> pFilterEntry(new FilterEntry);
772     pFilterEntry->aFilterName = CuiResId(RID_SVXSTR_GALLERY_ALLFILES);
773     pFilterEntry->aFilterName = addExtension(pFilterEntry->aFilterName, aExtensions);
774     m_xCbbFileType->insert_text(0, pFilterEntry->aFilterName);
775     m_xCbbFileType->set_active(0);
776     aFilterEntryList.insert(aFilterEntryList.begin(), std::move(pFilterEntry));
777 }
778 
IMPL_LINK_NOARG(TPGalleryThemeProperties,SelectFileTypeHdl,weld::ComboBox &,void)779 IMPL_LINK_NOARG(TPGalleryThemeProperties, SelectFileTypeHdl, weld::ComboBox&, void)
780 {
781     OUString aText(m_xCbbFileType->get_active_text());
782 
783     if( bInputAllowed && ( aLastFilterName != aText ) )
784     {
785         aLastFilterName = aText;
786 
787         std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryupdategalleryfilelistdialog.ui"));
788         std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("QueryUpdateFileListDialog"));
789         if (xQuery->run() == RET_YES)
790             SearchFiles();
791     }
792 }
793 
SearchFiles()794 void TPGalleryThemeProperties::SearchFiles()
795 {
796     std::shared_ptr<SearchProgress> xProgress(new SearchProgress(GetFrameWeld(), this, aURL));
797 
798     aFoundList.clear();
799     m_xLbxFound->clear();
800 
801     xProgress->SetFileType( m_xCbbFileType->get_active_text() );
802     xProgress->SetDirectory( INetURLObject() );
803 
804     xProgress->LaunchThread();
805     weld::DialogController::runAsync(xProgress, [this](sal_Int32 nResult) {
806         EndSearchProgressHdl(nResult);
807     });
808 }
809 
IMPL_LINK_NOARG(TPGalleryThemeProperties,ClickSearchHdl,weld::Button &,void)810 IMPL_LINK_NOARG(TPGalleryThemeProperties, ClickSearchHdl, weld::Button&, void)
811 {
812     if( bInputAllowed )
813     {
814         try
815         {
816             // setup folder picker
817             css::uno::Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
818             xFolderPicker = FolderPicker::create(xContext);
819 
820             OUString  aDlgPathName( SvtPathOptions().GetGraphicPath() );
821             xFolderPicker->setDisplayDirectory(aDlgPathName);
822 
823             aPreviewTimer.Stop();
824 
825             css::uno::Reference< XAsynchronousExecutableDialog > xAsyncDlg( xFolderPicker, UNO_QUERY );
826             if ( xAsyncDlg.is() )
827                 xAsyncDlg->startExecuteModal( xDialogListener.get() );
828             else
829             {
830                 if( xFolderPicker->execute() == RET_OK )
831                 {
832                     aURL = INetURLObject( xFolderPicker->getDirectory() );
833                     bSearchRecursive = true;    // UI choice no longer possible, windows file picker allows no user controls
834                     SearchFiles();
835                 }
836             }
837         }
838         catch (const IllegalArgumentException&)
839         {
840             OSL_FAIL( "Folder picker failed with illegal arguments" );
841         }
842     }
843 }
844 
TakeFiles()845 void TPGalleryThemeProperties::TakeFiles()
846 {
847     if (m_xLbxFound->count_selected_rows() || (bTakeAll && bEntriesFound))
848     {
849         std::shared_ptr<TakeProgress> xTakeProgress(new TakeProgress(GetFrameWeld(), this));
850         xTakeProgress->LaunchThread();
851         weld::DialogController::runAsync(xTakeProgress, [=](sal_Int32 /*nResult*/) {
852             /* no postprocessing needed, pTakeProgress
853                will be disposed in TakeProgress::CleanupHdl */
854         });
855 
856     }
857 }
858 
IMPL_LINK_NOARG(TPGalleryThemeProperties,ClickPreviewHdl,weld::ToggleButton &,void)859 IMPL_LINK_NOARG(TPGalleryThemeProperties, ClickPreviewHdl, weld::ToggleButton&, void)
860 {
861     if ( bInputAllowed )
862     {
863         aPreviewTimer.Stop();
864         aPreviewString.clear();
865 
866         if (!m_xCbxPreview->get_active())
867         {
868             xMediaPlayer.clear();
869             m_aWndPreview.SetGraphic(Graphic());
870             m_aWndPreview.Invalidate();
871         }
872         else
873             DoPreview();
874     }
875 }
876 
DoPreview()877 void TPGalleryThemeProperties::DoPreview()
878 {
879     int nIndex = m_xLbxFound->get_selected_index();
880     OUString aString(m_xLbxFound->get_text(nIndex));
881 
882     if (aString != aPreviewString)
883     {
884         INetURLObject _aURL(aFoundList[nIndex]);
885         bInputAllowed = false;
886 
887         if (!m_aWndPreview.SetGraphic(_aURL))
888         {
889             weld::WaitObject aWaitObject(GetFrameWeld());
890             ErrorHandler::HandleError(ERRCODE_IO_NOTEXISTSPATH, GetFrameWeld());
891         }
892 #if HAVE_FEATURE_AVMEDIA
893         else if( ::avmedia::MediaWindow::isMediaURL( _aURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ), "" ) )
894         {
895             xMediaPlayer = ::avmedia::MediaWindow::createPlayer( _aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), "" );
896             if( xMediaPlayer.is() )
897                 xMediaPlayer->start();
898         }
899 #endif
900         bInputAllowed = true;
901         aPreviewString = aString;
902     }
903 }
904 
IMPL_LINK_NOARG(TPGalleryThemeProperties,ClickTakeHdl,weld::Button &,void)905 IMPL_LINK_NOARG(TPGalleryThemeProperties, ClickTakeHdl, weld::Button&, void)
906 {
907     if( bInputAllowed )
908     {
909         aPreviewTimer.Stop();
910 
911         if (!m_xLbxFound->count_selected_rows() || !bEntriesFound)
912         {
913             SvxOpenGraphicDialog aDlg(CuiResId(RID_SVXSTR_KEY_GALLERY_DIR), GetFrameWeld());
914             aDlg.EnableLink(false);
915             aDlg.AsLink(false);
916 
917             if( !aDlg.Execute() )
918                 pData->pTheme->InsertURL( INetURLObject( aDlg.GetPath() ) );
919         }
920         else
921         {
922             bTakeAll = false;
923             TakeFiles();
924         }
925     }
926 }
927 
IMPL_LINK_NOARG(TPGalleryThemeProperties,ClickTakeAllHdl,weld::Button &,void)928 IMPL_LINK_NOARG(TPGalleryThemeProperties, ClickTakeAllHdl, weld::Button&, void)
929 {
930     if( bInputAllowed )
931     {
932         aPreviewTimer.Stop();
933         bTakeAll = true;
934         TakeFiles();
935     }
936 }
937 
IMPL_LINK_NOARG(TPGalleryThemeProperties,SelectFoundHdl,weld::TreeView &,void)938 IMPL_LINK_NOARG(TPGalleryThemeProperties, SelectFoundHdl, weld::TreeView&, void)
939 {
940     if (bInputAllowed)
941     {
942         bool bPreviewPossible = false;
943 
944         aPreviewTimer.Stop();
945 
946         if( bEntriesFound )
947         {
948             if (m_xLbxFound->count_selected_rows() == 1)
949             {
950                 m_xCbxPreview->set_sensitive(true);
951                 bPreviewPossible = true;
952             }
953             else
954                 m_xCbxPreview->set_sensitive(false);
955 
956             if( !aFoundList.empty() )
957                 m_xBtnTakeAll->set_sensitive(true);
958             else
959                 m_xBtnTakeAll->set_sensitive(false);
960         }
961 
962         if (bPreviewPossible && m_xCbxPreview->get_active())
963             aPreviewTimer.Start();
964     }
965 }
966 
IMPL_LINK_NOARG(TPGalleryThemeProperties,DClickFoundHdl,weld::TreeView &,bool)967 IMPL_LINK_NOARG(TPGalleryThemeProperties, DClickFoundHdl, weld::TreeView&, bool)
968 {
969     if( bInputAllowed )
970     {
971         aPreviewTimer.Stop();
972 
973         if (m_xLbxFound->count_selected_rows() == 1 && bEntriesFound)
974             ClickTakeHdl(*m_xBtnTake);
975     }
976     return true;
977 }
978 
IMPL_LINK_NOARG(TPGalleryThemeProperties,PreviewTimerHdl,Timer *,void)979 IMPL_LINK_NOARG(TPGalleryThemeProperties, PreviewTimerHdl, Timer *, void)
980 {
981     aPreviewTimer.Stop();
982     DoPreview();
983 }
984 
EndSearchProgressHdl(sal_Int32)985 void TPGalleryThemeProperties::EndSearchProgressHdl(sal_Int32 /*nResult*/)
986 {
987   if( !aFoundList.empty() )
988   {
989       m_xLbxFound->select(0);
990       m_xBtnTakeAll->set_sensitive(true);
991       m_xCbxPreview->set_sensitive(true);
992       bEntriesFound = true;
993   }
994   else
995   {
996       m_xLbxFound->append_text(CuiResId(RID_SVXSTR_GALLERY_NOFILES));
997       m_xBtnTakeAll->set_sensitive(false);
998       m_xCbxPreview->set_sensitive(false);
999       bEntriesFound = false;
1000   }
1001 }
1002 
IMPL_LINK(TPGalleryThemeProperties,DialogClosedHdl,css::ui::dialogs::DialogClosedEvent *,pEvt,void)1003 IMPL_LINK( TPGalleryThemeProperties, DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, pEvt, void )
1004 {
1005     DBG_ASSERT( xFolderPicker.is(), "TPGalleryThemeProperties::DialogClosedHdl(): no folder picker" );
1006 
1007     OUString sURL = xFolderPicker->getDirectory();
1008     StartSearchFiles( sURL, pEvt->DialogResult );
1009 }
1010 
1011 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1012