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>
23 #include <vcl/commandevent.hxx>
24 #include <vcl/event.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/weld.hxx>
27 #include <com/sun/star/ucb/ContentCreationException.hpp>
28 #include <sfx2/app.hxx>
30 #include <svx/gallery1.hxx>
31 #include <svx/galtheme.hxx>
32 #include <svx/galmisc.hxx>
33 #include "galbrws1.hxx"
34 #include <svx/strings.hrc>
36 #include <svx/dialmgr.hxx>
37 #include <comphelper/dispatchcommand.hxx>
38 #include <com/sun/star/beans/PropertyValue.hpp>
39 #include <svx/svxdlg.hxx>
41 #include <bitmaps.hlst>
43 using namespace ::com::sun::star
;
45 GalleryBrowser1::GalleryBrowser1(
46 weld::Builder
& rBuilder
,
48 const std::function
<void ()>& rThemeSelectionHandler
)
50 mxNewTheme(rBuilder
.weld_button("insert")),
51 mxThemes(rBuilder
.weld_tree_view("themelist")),
52 mxMoreGalleries(rBuilder
.weld_button("btnMoreGalleries")),
53 mpGallery ( pGallery
),
54 mpExchangeData ( new ExchangeData
),
55 aImgNormal ( RID_SVXBMP_THEME_NORMAL
),
56 aImgDefault ( RID_SVXBMP_THEME_DEFAULT
),
57 aImgReadOnly ( RID_SVXBMP_THEME_READONLY
),
58 maThemeSelectionHandler(rThemeSelectionHandler
)
60 mxNewTheme
->set_help_id(HID_GALLERY_NEWTHEME
);
61 mxNewTheme
->connect_clicked( LINK( this, GalleryBrowser1
, ClickNewThemeHdl
) );
63 mxThemes
->make_sorted();
64 mxThemes
->set_help_id( HID_GALLERY_THEMELIST
);
65 mxThemes
->connect_changed( LINK( this, GalleryBrowser1
, SelectThemeHdl
) );
66 mxThemes
->connect_popup_menu(LINK(this, GalleryBrowser1
, PopupMenuHdl
));
67 mxThemes
->connect_key_press(LINK(this, GalleryBrowser1
, KeyInputHdl
));
68 mxThemes
->set_size_request(-1, mxThemes
->get_height_rows(6));
70 mxMoreGalleries
->set_from_icon_name("cmd/sc_additionsdialog.png");
71 mxMoreGalleries
->connect_clicked(LINK(this, GalleryBrowser1
, OnMoreGalleriesClick
));
73 // disable creation of new themes if a writable directory is not available
74 if( mpGallery
->GetUserURL().GetProtocol() == INetProtocol::NotValid
)
75 mxNewTheme
->set_sensitive(false);
77 StartListening( *mpGallery
);
79 for (size_t i
= 0, nCount
= mpGallery
->GetThemeCount(); i
< nCount
; ++i
)
80 ImplInsertThemeEntry( mpGallery
->GetThemeInfo( i
) );
83 GalleryBrowser1::~GalleryBrowser1()
85 EndListening( *mpGallery
);
86 mpExchangeData
.reset();
89 void GalleryBrowser1::ImplInsertThemeEntry( const GalleryThemeEntry
* pEntry
)
91 static const bool bShowHiddenThemes
= ( getenv( "GALLERY_SHOW_HIDDEN_THEMES" ) != nullptr );
93 if( !(pEntry
&& ( !pEntry
->IsHidden() || bShowHiddenThemes
)) )
96 const OUString
* pImage
;
98 if( pEntry
->IsReadOnly() )
99 pImage
= &aImgReadOnly
;
100 else if( pEntry
->IsDefault() )
101 pImage
= &aImgDefault
;
103 pImage
= &aImgNormal
;
105 mxThemes
->append("", pEntry
->GetThemeName(), *pImage
);
108 void GalleryBrowser1::ImplFillExchangeData( const GalleryTheme
* pThm
, ExchangeData
& rData
)
110 rData
.pTheme
= const_cast<GalleryTheme
*>(pThm
);
111 rData
.aEditedTitle
= pThm
->GetName();
115 DateTime
aDateTime(pThm
->getModificationDate());
117 rData
.aThemeChangeDate
= aDateTime
;
118 rData
.aThemeChangeTime
= aDateTime
;
120 catch( const ucb::ContentCreationException
& )
123 catch( const uno::RuntimeException
& )
126 catch( const uno::Exception
& )
131 void GalleryBrowser1::ImplGetExecuteVector(std::vector
<OString
>& o_aExec
)
133 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( GetSelectedTheme(), *this );
138 bool bUpdateAllowed
, bRenameAllowed
, bRemoveAllowed
;
139 static const bool bIdDialog
= ( getenv( "GALLERY_ENABLE_ID_DIALOG" ) != nullptr );
141 if( pTheme
->IsReadOnly() )
142 bUpdateAllowed
= bRenameAllowed
= bRemoveAllowed
= false;
143 else if( pTheme
->IsDefault() )
145 bUpdateAllowed
= bRenameAllowed
= true;
146 bRemoveAllowed
= false;
149 bUpdateAllowed
= bRenameAllowed
= bRemoveAllowed
= true;
151 if( bUpdateAllowed
&& pTheme
->GetObjectCount() )
152 o_aExec
.emplace_back("update");
155 o_aExec
.emplace_back("rename");
158 o_aExec
.emplace_back("delete");
160 if( bIdDialog
&& !pTheme
->IsReadOnly() )
161 o_aExec
.emplace_back("assign");
163 o_aExec
.emplace_back("properties");
165 mpGallery
->ReleaseTheme( pTheme
, *this );
168 void GalleryBrowser1::ImplGalleryThemeProperties( std::u16string_view rThemeName
, bool bCreateNew
)
170 DBG_ASSERT(!mpThemePropsDlgItemSet
, "mpThemePropsDlgItemSet already set!");
171 mpThemePropsDlgItemSet
.reset(new SfxItemSet( SfxGetpApp()->GetPool() ));
172 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( rThemeName
, *this );
174 ImplFillExchangeData( pTheme
, *mpExchangeData
);
176 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
177 VclPtr
<VclAbstractDialog
> xThemePropertiesDialog
= pFact
->CreateGalleryThemePropertiesDialog(mxThemes
.get(), mpExchangeData
.get(), mpThemePropsDlgItemSet
.get());
181 xThemePropertiesDialog
->StartExecuteAsync([xThemePropertiesDialog
, this](sal_Int32 nResult
){
182 EndNewThemePropertiesDlgHdl(nResult
);
183 xThemePropertiesDialog
->disposeOnce();
188 xThemePropertiesDialog
->StartExecuteAsync([xThemePropertiesDialog
, this](sal_Int32 nResult
){
189 EndThemePropertiesDlgHdl(nResult
);
190 xThemePropertiesDialog
->disposeOnce();
195 void GalleryBrowser1::ImplEndGalleryThemeProperties(bool bCreateNew
, sal_Int32 nRet
)
199 OUString
aName( mpExchangeData
->pTheme
->GetName() );
201 if( !mpExchangeData
->aEditedTitle
.isEmpty() && aName
!= mpExchangeData
->aEditedTitle
)
203 OUString
aTitle( mpExchangeData
->aEditedTitle
);
204 sal_uInt16 nCount
= 0;
206 while( mpGallery
->HasTheme( aTitle
) && ( nCount
++ < 16000 ) )
208 aTitle
= mpExchangeData
->aEditedTitle
+ " " + OUString::number( nCount
);
211 mpGallery
->RenameTheme( aName
, aTitle
);
216 mxThemes
->select_text( mpExchangeData
->pTheme
->GetName() );
217 SelectThemeHdl( *mxThemes
);
221 OUString
aThemeName( mpExchangeData
->pTheme
->GetName() );
222 mpGallery
->ReleaseTheme( mpExchangeData
->pTheme
, *this );
224 if ( bCreateNew
&& ( nRet
!= RET_OK
) )
226 mpGallery
->RemoveTheme( aThemeName
);
230 void GalleryBrowser1::EndNewThemePropertiesDlgHdl(sal_Int32 nResult
)
232 ImplEndGalleryThemeProperties(true, nResult
);
235 void GalleryBrowser1::EndThemePropertiesDlgHdl(sal_Int32 nResult
)
237 ImplEndGalleryThemeProperties(false, nResult
);
240 void GalleryBrowser1::ImplExecute(std::string_view rIdent
)
242 if (rIdent
== "update")
244 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( GetSelectedTheme(), *this );
246 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
247 ScopedVclPtr
<VclAbstractDialog
> aActualizeProgress(pFact
->CreateActualizeProgressDialog(mxThemes
.get(), pTheme
));
249 aActualizeProgress
->Execute();
250 mpGallery
->ReleaseTheme( pTheme
, *this );
252 else if (rIdent
== "delete")
254 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(mxThemes
.get(), "svx/ui/querydeletethemedialog.ui"));
255 std::unique_ptr
<weld::MessageDialog
> xQuery(xBuilder
->weld_message_dialog("QueryDeleteThemeDialog"));
256 if (xQuery
->run() == RET_YES
)
257 mpGallery
->RemoveTheme( mxThemes
->get_selected_text() );
259 else if (rIdent
== "rename")
261 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( GetSelectedTheme(), *this );
262 const OUString
aOldName( pTheme
->GetName() );
264 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
265 ScopedVclPtr
<AbstractTitleDialog
> aDlg(pFact
->CreateTitleDialog(mxThemes
.get(), aOldName
));
267 if( aDlg
->Execute() == RET_OK
)
269 const OUString
aNewName( aDlg
->GetTitle() );
271 if( !aNewName
.isEmpty() && ( aNewName
!= aOldName
) )
273 OUString
aName( aNewName
);
274 sal_uInt16 nCount
= 0;
276 while( mpGallery
->HasTheme( aName
) && ( nCount
++ < 16000 ) )
278 aName
= aNewName
+ " " + OUString::number( nCount
);
281 mpGallery
->RenameTheme( aOldName
, aName
);
284 mpGallery
->ReleaseTheme( pTheme
, *this );
286 else if (rIdent
== "assign")
288 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( GetSelectedTheme(), *this );
290 if (pTheme
&& !pTheme
->IsReadOnly())
293 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
294 ScopedVclPtr
<AbstractGalleryIdDialog
> aDlg(pFact
->CreateGalleryIdDialog(mxThemes
.get(), pTheme
));
295 if( aDlg
->Execute() == RET_OK
)
296 pTheme
->SetId( aDlg
->GetId(), true );
299 mpGallery
->ReleaseTheme( pTheme
, *this );
301 else if (rIdent
== "properties")
303 ImplGalleryThemeProperties( GetSelectedTheme(), false );
307 void GalleryBrowser1::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
309 const GalleryHint
& rGalleryHint
= static_cast<const GalleryHint
&>(rHint
);
311 switch( rGalleryHint
.GetType() )
313 case GalleryHintType::THEME_CREATED
:
314 ImplInsertThemeEntry( mpGallery
->GetThemeInfo( rGalleryHint
.GetThemeName() ) );
317 case GalleryHintType::THEME_RENAMED
:
319 const sal_Int32 nCurSelectPos
= mxThemes
->get_selected_index();
320 const sal_Int32 nRenameEntryPos
= mxThemes
->find_text( rGalleryHint
.GetThemeName() );
322 mxThemes
->remove_text( rGalleryHint
.GetThemeName() );
323 ImplInsertThemeEntry( mpGallery
->GetThemeInfo( rGalleryHint
.GetStringData() ) );
325 if( nCurSelectPos
== nRenameEntryPos
)
327 mxThemes
->select_text( rGalleryHint
.GetStringData() );
328 SelectThemeHdl( *mxThemes
);
333 case GalleryHintType::THEME_REMOVED
:
335 mxThemes
->remove_text( rGalleryHint
.GetThemeName() );
339 case GalleryHintType::CLOSE_THEME
:
341 const sal_Int32 nCurSelectPos
= mxThemes
->get_selected_index();
342 const sal_Int32 nCloseEntryPos
= mxThemes
->find_text( rGalleryHint
.GetThemeName() );
344 if( nCurSelectPos
== nCloseEntryPos
)
346 if( nCurSelectPos
< ( mxThemes
->n_children() - 1 ) )
347 mxThemes
->select( nCurSelectPos
+ 1 );
348 else if( nCurSelectPos
)
349 mxThemes
->select( nCurSelectPos
- 1 );
351 mxThemes
->select(-1);
353 SelectThemeHdl( *mxThemes
);
363 IMPL_STATIC_LINK_NOARG( GalleryBrowser1
, OnMoreGalleriesClick
, weld::Button
&, void)
365 css::uno::Sequence
<css::beans::PropertyValue
> aArgs(1);
366 aArgs
[0].Name
= "AdditionsTag";
367 aArgs
[0].Value
<<= OUString("Gallery");
368 comphelper::dispatchCommand(".uno:AdditionsDialog", aArgs
);
371 IMPL_LINK(GalleryBrowser1
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
375 std::vector
<OString
> aExecVector
;
376 ImplGetExecuteVector(aExecVector
);
377 OString sExecuteIdent
;
378 bool bMod1
= rKEvt
.GetKeyCode().IsMod1();
380 switch( rKEvt
.GetKeyCode().GetCode() )
383 ClickNewThemeHdl(*mxNewTheme
);
389 ClickNewThemeHdl(*mxNewTheme
);
396 sExecuteIdent
= "update";
401 sExecuteIdent
= "delete";
407 sExecuteIdent
= "delete";
414 sExecuteIdent
= "rename";
421 sExecuteIdent
= "properties";
426 if (!sExecuteIdent
.isEmpty() && (std::find( aExecVector
.begin(), aExecVector
.end(), sExecuteIdent
) != aExecVector
.end()))
428 ImplExecute(sExecuteIdent
);
435 IMPL_LINK(GalleryBrowser1
, PopupMenuHdl
, const CommandEvent
&, rCEvt
, bool)
437 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
)
440 std::vector
<OString
> aExecVector
;
441 ImplGetExecuteVector(aExecVector
);
443 if (aExecVector
.empty())
446 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(mxThemes
.get(), "svx/ui/gallerymenu1.ui"));
447 std::unique_ptr
<weld::Menu
> xMenu(xBuilder
->weld_menu("menu"));
449 xMenu
->set_visible("update", std::find( aExecVector
.begin(), aExecVector
.end(), "update" ) != aExecVector
.end());
450 xMenu
->set_visible("rename", std::find( aExecVector
.begin(), aExecVector
.end(), "rename" ) != aExecVector
.end());
451 xMenu
->set_visible("delete", std::find( aExecVector
.begin(), aExecVector
.end(), "delete" ) != aExecVector
.end());
452 xMenu
->set_visible("assign", std::find( aExecVector
.begin(), aExecVector
.end(), "assign" ) != aExecVector
.end());
453 xMenu
->set_visible("properties", std::find( aExecVector
.begin(), aExecVector
.end(), "properties" ) != aExecVector
.end());
455 OString
sCommand(xMenu
->popup_at_rect(mxThemes
.get(), tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1,1))));
456 ImplExecute(sCommand
);
461 IMPL_LINK_NOARG(GalleryBrowser1
, SelectThemeHdl
, weld::TreeView
&, void)
463 if (maThemeSelectionHandler
)
464 maThemeSelectionHandler();
467 IMPL_LINK_NOARG(GalleryBrowser1
, ClickNewThemeHdl
, weld::Button
&, void)
469 OUString
aNewTheme( SvxResId(RID_SVXSTR_GALLERY_NEWTHEME
) );
470 OUString
aName( aNewTheme
);
471 sal_uInt16 nCount
= 0;
473 while( mpGallery
->HasTheme( aName
) && ( nCount
++ < 16000 ) )
475 aName
= aNewTheme
+ " " + OUString::number( nCount
);
478 if( !mpGallery
->HasTheme( aName
) && mpGallery
->CreateTheme( aName
) )
480 ImplGalleryThemeProperties( aName
, true );
484 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */