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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <tools/datetime.hxx>
24 #include <vcl/commandevent.hxx>
25 #include <vcl/event.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/weld.hxx>
28 #include <com/sun/star/ucb/ContentCreationException.hpp>
29 #include <sfx2/app.hxx>
31 #include <svx/gallery1.hxx>
32 #include <svx/galtheme.hxx>
33 #include <svx/galmisc.hxx>
34 #include "galbrws1.hxx"
35 #include <svx/strings.hrc>
37 #include <svx/dialmgr.hxx>
38 #include <comphelper/dispatchcommand.hxx>
39 #include <comphelper/propertyvalue.hxx>
40 #include <com/sun/star/beans/PropertyValue.hpp>
41 #include <svx/svxdlg.hxx>
43 #include <bitmaps.hlst>
45 using namespace ::com::sun::star
;
47 GalleryBrowser1::GalleryBrowser1(
48 weld::Builder
& rBuilder
,
50 std::function
<void ()> aThemeSelectionHandler
)
52 mxNewTheme(rBuilder
.weld_button("insert")),
53 mxThemes(rBuilder
.weld_tree_view("themelist")),
54 mxMoreGalleries(rBuilder
.weld_button("btnMoreGalleries")),
55 mpGallery ( pGallery
),
56 mpExchangeData ( new ExchangeData
),
57 aImgNormal ( RID_SVXBMP_THEME_NORMAL
),
58 aImgDefault ( RID_SVXBMP_THEME_DEFAULT
),
59 aImgReadOnly ( RID_SVXBMP_THEME_READONLY
),
60 maThemeSelectionHandler(std::move(aThemeSelectionHandler
))
62 mxNewTheme
->set_help_id(HID_GALLERY_NEWTHEME
);
63 mxNewTheme
->connect_clicked( LINK( this, GalleryBrowser1
, ClickNewThemeHdl
) );
65 mxThemes
->make_sorted();
66 mxThemes
->set_help_id( HID_GALLERY_THEMELIST
);
67 mxThemes
->connect_changed( LINK( this, GalleryBrowser1
, SelectThemeHdl
) );
68 mxThemes
->connect_popup_menu(LINK(this, GalleryBrowser1
, PopupMenuHdl
));
69 mxThemes
->connect_key_press(LINK(this, GalleryBrowser1
, KeyInputHdl
));
70 mxThemes
->set_size_request(-1, mxThemes
->get_height_rows(6));
72 mxMoreGalleries
->connect_clicked(LINK(this, GalleryBrowser1
, OnMoreGalleriesClick
));
74 // disable creation of new themes if a writable directory is not available
75 if( mpGallery
->GetUserURL().GetProtocol() == INetProtocol::NotValid
)
76 mxNewTheme
->set_sensitive(false);
78 StartListening( *mpGallery
);
80 for (size_t i
= 0, nCount
= mpGallery
->GetThemeCount(); i
< nCount
; ++i
)
81 ImplInsertThemeEntry( mpGallery
->GetThemeInfo( i
) );
84 GalleryBrowser1::~GalleryBrowser1()
86 EndListening( *mpGallery
);
87 mpExchangeData
.reset();
90 void GalleryBrowser1::ImplInsertThemeEntry( const GalleryThemeEntry
* pEntry
)
92 static const bool bShowHiddenThemes
= ( getenv( "GALLERY_SHOW_HIDDEN_THEMES" ) != nullptr );
94 if( !(pEntry
&& ( !pEntry
->IsHidden() || bShowHiddenThemes
)) )
97 const OUString
* pImage
;
99 if( pEntry
->IsReadOnly() )
100 pImage
= &aImgReadOnly
;
101 else if( pEntry
->IsDefault() )
102 pImage
= &aImgDefault
;
104 pImage
= &aImgNormal
;
106 mxThemes
->append("", pEntry
->GetThemeName(), *pImage
);
109 void GalleryBrowser1::ImplFillExchangeData( const GalleryTheme
* pThm
, ExchangeData
& rData
)
111 rData
.pTheme
= const_cast<GalleryTheme
*>(pThm
);
112 rData
.aEditedTitle
= pThm
->GetName();
116 DateTime
aDateTime(pThm
->getModificationDate());
118 rData
.aThemeChangeDate
= aDateTime
;
119 rData
.aThemeChangeTime
= aDateTime
;
121 catch( const ucb::ContentCreationException
& )
124 catch( const uno::RuntimeException
& )
127 catch( const uno::Exception
& )
132 void GalleryBrowser1::ImplGetExecuteVector(std::vector
<OUString
>& o_aExec
)
134 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( GetSelectedTheme(), *this );
139 bool bUpdateAllowed
, bRenameAllowed
, bRemoveAllowed
;
140 static const bool bIdDialog
= ( getenv( "GALLERY_ENABLE_ID_DIALOG" ) != nullptr );
142 if( pTheme
->IsReadOnly() )
143 bUpdateAllowed
= bRenameAllowed
= bRemoveAllowed
= false;
144 else if( pTheme
->IsDefault() )
146 bUpdateAllowed
= bRenameAllowed
= true;
147 bRemoveAllowed
= false;
150 bUpdateAllowed
= bRenameAllowed
= bRemoveAllowed
= true;
152 if( bUpdateAllowed
&& pTheme
->GetObjectCount() )
153 o_aExec
.emplace_back("update");
156 o_aExec
.emplace_back("rename");
159 o_aExec
.emplace_back("delete");
161 if( bIdDialog
&& !pTheme
->IsReadOnly() )
162 o_aExec
.emplace_back("assign");
164 o_aExec
.emplace_back("properties");
166 mpGallery
->ReleaseTheme( pTheme
, *this );
169 void GalleryBrowser1::ImplGalleryThemeProperties( std::u16string_view rThemeName
, bool bCreateNew
)
171 DBG_ASSERT(!mpThemePropsDlgItemSet
, "mpThemePropsDlgItemSet already set!");
172 mpThemePropsDlgItemSet
.reset(new SfxItemSet( SfxGetpApp()->GetPool() ));
173 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( rThemeName
, *this );
175 ImplFillExchangeData( pTheme
, *mpExchangeData
);
177 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
178 VclPtr
<VclAbstractDialog
> xThemePropertiesDialog
= pFact
->CreateGalleryThemePropertiesDialog(mxThemes
.get(), mpExchangeData
.get(), mpThemePropsDlgItemSet
.get());
182 xThemePropertiesDialog
->StartExecuteAsync([xThemePropertiesDialog
, this](sal_Int32 nResult
){
183 EndNewThemePropertiesDlgHdl(nResult
);
184 xThemePropertiesDialog
->disposeOnce();
189 xThemePropertiesDialog
->StartExecuteAsync([xThemePropertiesDialog
, this](sal_Int32 nResult
){
190 EndThemePropertiesDlgHdl(nResult
);
191 xThemePropertiesDialog
->disposeOnce();
196 void GalleryBrowser1::ImplEndGalleryThemeProperties(bool bCreateNew
, sal_Int32 nRet
)
200 OUString
aName( mpExchangeData
->pTheme
->GetName() );
202 if( !mpExchangeData
->aEditedTitle
.isEmpty() && aName
!= mpExchangeData
->aEditedTitle
)
204 OUString
aTitle( mpExchangeData
->aEditedTitle
);
205 sal_uInt16 nCount
= 0;
207 while( mpGallery
->HasTheme( aTitle
) && ( nCount
++ < 16000 ) )
209 aTitle
= mpExchangeData
->aEditedTitle
+ " " + OUString::number( nCount
);
212 mpGallery
->RenameTheme( aName
, aTitle
);
217 mxThemes
->select_text( mpExchangeData
->pTheme
->GetName() );
218 SelectThemeHdl( *mxThemes
);
222 OUString
aThemeName( mpExchangeData
->pTheme
->GetName() );
223 mpGallery
->ReleaseTheme( mpExchangeData
->pTheme
, *this );
225 if ( bCreateNew
&& ( nRet
!= RET_OK
) )
227 mpGallery
->RemoveTheme( aThemeName
);
231 void GalleryBrowser1::EndNewThemePropertiesDlgHdl(sal_Int32 nResult
)
233 ImplEndGalleryThemeProperties(true, nResult
);
236 void GalleryBrowser1::EndThemePropertiesDlgHdl(sal_Int32 nResult
)
238 ImplEndGalleryThemeProperties(false, nResult
);
241 void GalleryBrowser1::ImplExecute(std::u16string_view rIdent
)
243 if (rIdent
== u
"update")
245 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( GetSelectedTheme(), *this );
247 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
248 ScopedVclPtr
<VclAbstractDialog
> aActualizeProgress(pFact
->CreateActualizeProgressDialog(mxThemes
.get(), pTheme
));
250 aActualizeProgress
->Execute();
251 mpGallery
->ReleaseTheme( pTheme
, *this );
253 else if (rIdent
== u
"delete")
255 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(mxThemes
.get(), "svx/ui/querydeletethemedialog.ui"));
256 std::unique_ptr
<weld::MessageDialog
> xQuery(xBuilder
->weld_message_dialog("QueryDeleteThemeDialog"));
257 if (xQuery
->run() == RET_YES
)
258 mpGallery
->RemoveTheme( mxThemes
->get_selected_text() );
260 else if (rIdent
== u
"rename")
262 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( GetSelectedTheme(), *this );
263 const OUString
aOldName( pTheme
->GetName() );
265 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
266 ScopedVclPtr
<AbstractTitleDialog
> aDlg(pFact
->CreateTitleDialog(mxThemes
.get(), aOldName
));
268 if( aDlg
->Execute() == RET_OK
)
270 const OUString
aNewName( aDlg
->GetTitle() );
272 if( !aNewName
.isEmpty() && ( aNewName
!= aOldName
) )
274 OUString
aName( aNewName
);
275 sal_uInt16 nCount
= 0;
277 while( mpGallery
->HasTheme( aName
) && ( nCount
++ < 16000 ) )
279 aName
= aNewName
+ " " + OUString::number( nCount
);
282 mpGallery
->RenameTheme( aOldName
, aName
);
285 mpGallery
->ReleaseTheme( pTheme
, *this );
287 else if (rIdent
== u
"assign")
289 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( GetSelectedTheme(), *this );
291 if (pTheme
&& !pTheme
->IsReadOnly())
294 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
295 ScopedVclPtr
<AbstractGalleryIdDialog
> aDlg(pFact
->CreateGalleryIdDialog(mxThemes
.get(), pTheme
));
296 if( aDlg
->Execute() == RET_OK
)
297 pTheme
->SetId( aDlg
->GetId(), true );
300 mpGallery
->ReleaseTheme( pTheme
, *this );
302 else if (rIdent
== u
"properties")
304 ImplGalleryThemeProperties( GetSelectedTheme(), false );
308 void GalleryBrowser1::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
310 const GalleryHint
& rGalleryHint
= static_cast<const GalleryHint
&>(rHint
);
312 switch( rGalleryHint
.GetType() )
314 case GalleryHintType::THEME_CREATED
:
315 ImplInsertThemeEntry( mpGallery
->GetThemeInfo( rGalleryHint
.GetThemeName() ) );
318 case GalleryHintType::THEME_RENAMED
:
320 const sal_Int32 nCurSelectPos
= mxThemes
->get_selected_index();
321 const sal_Int32 nRenameEntryPos
= mxThemes
->find_text( rGalleryHint
.GetThemeName() );
323 mxThemes
->remove_text( rGalleryHint
.GetThemeName() );
324 ImplInsertThemeEntry( mpGallery
->GetThemeInfo( rGalleryHint
.GetStringData() ) );
326 if( nCurSelectPos
== nRenameEntryPos
)
328 mxThemes
->select_text( rGalleryHint
.GetStringData() );
329 SelectThemeHdl( *mxThemes
);
334 case GalleryHintType::THEME_REMOVED
:
336 mxThemes
->remove_text( rGalleryHint
.GetThemeName() );
340 case GalleryHintType::CLOSE_THEME
:
342 const sal_Int32 nCurSelectPos
= mxThemes
->get_selected_index();
343 const sal_Int32 nCloseEntryPos
= mxThemes
->find_text( rGalleryHint
.GetThemeName() );
345 if( nCurSelectPos
== nCloseEntryPos
)
347 if( nCurSelectPos
< ( mxThemes
->n_children() - 1 ) )
348 mxThemes
->select( nCurSelectPos
+ 1 );
349 else if( nCurSelectPos
)
350 mxThemes
->select( nCurSelectPos
- 1 );
352 mxThemes
->select(-1);
354 SelectThemeHdl( *mxThemes
);
364 IMPL_STATIC_LINK_NOARG( GalleryBrowser1
, OnMoreGalleriesClick
, weld::Button
&, void)
366 css::uno::Sequence
<css::beans::PropertyValue
> aArgs
{
367 comphelper::makePropertyValue("AdditionsTag", OUString("Gallery"))
369 comphelper::dispatchCommand(".uno:AdditionsDialog", aArgs
);
372 IMPL_LINK(GalleryBrowser1
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
376 std::vector
<OUString
> aExecVector
;
377 ImplGetExecuteVector(aExecVector
);
378 OUString sExecuteIdent
;
379 bool bMod1
= rKEvt
.GetKeyCode().IsMod1();
381 switch( rKEvt
.GetKeyCode().GetCode() )
384 ClickNewThemeHdl(*mxNewTheme
);
390 ClickNewThemeHdl(*mxNewTheme
);
397 sExecuteIdent
= "update";
402 sExecuteIdent
= "delete";
408 sExecuteIdent
= "delete";
415 sExecuteIdent
= "rename";
422 sExecuteIdent
= "properties";
427 if (!sExecuteIdent
.isEmpty() && (std::find( aExecVector
.begin(), aExecVector
.end(), sExecuteIdent
) != aExecVector
.end()))
429 ImplExecute(sExecuteIdent
);
436 IMPL_LINK(GalleryBrowser1
, PopupMenuHdl
, const CommandEvent
&, rCEvt
, bool)
438 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
)
441 std::vector
<OUString
> aExecVector
;
442 ImplGetExecuteVector(aExecVector
);
444 if (aExecVector
.empty())
447 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(mxThemes
.get(), "svx/ui/gallerymenu1.ui"));
448 std::unique_ptr
<weld::Menu
> xMenu(xBuilder
->weld_menu("menu"));
450 xMenu
->set_visible("update", std::find( aExecVector
.begin(), aExecVector
.end(), "update" ) != aExecVector
.end());
451 xMenu
->set_visible("rename", std::find( aExecVector
.begin(), aExecVector
.end(), "rename" ) != aExecVector
.end());
452 xMenu
->set_visible("delete", std::find( aExecVector
.begin(), aExecVector
.end(), "delete" ) != aExecVector
.end());
453 xMenu
->set_visible("assign", std::find( aExecVector
.begin(), aExecVector
.end(), "assign" ) != aExecVector
.end());
454 xMenu
->set_visible("properties", std::find( aExecVector
.begin(), aExecVector
.end(), "properties" ) != aExecVector
.end());
456 OUString
sCommand(xMenu
->popup_at_rect(mxThemes
.get(), tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1,1))));
457 ImplExecute(sCommand
);
462 IMPL_LINK_NOARG(GalleryBrowser1
, SelectThemeHdl
, weld::TreeView
&, void)
464 if (maThemeSelectionHandler
)
465 maThemeSelectionHandler();
468 IMPL_LINK_NOARG(GalleryBrowser1
, ClickNewThemeHdl
, weld::Button
&, void)
470 OUString
aNewTheme( SvxResId(RID_SVXSTR_GALLERY_NEWTHEME
) );
471 OUString
aName( aNewTheme
);
472 sal_uInt16 nCount
= 0;
474 while( mpGallery
->HasTheme( aName
) && ( nCount
++ < 16000 ) )
476 aName
= aNewTheme
+ " " + OUString::number( nCount
);
479 if( !mpGallery
->HasTheme( aName
) && mpGallery
->CreateTheme( aName
) )
481 ImplGalleryThemeProperties( aName
, true );
485 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */