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