tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / svx / source / gallery2 / galbrws1.cxx
blob2346410b30851f3b40805b67f021aaac5fe1c95d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <tools/wldcrd.hxx>
24 #include <utility>
25 #include <vcl/commandevent.hxx>
26 #include <vcl/event.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/weld.hxx>
29 #include <vcl/graphicfilter.hxx>
30 #include <vcl/virdev.hxx>
31 #include <com/sun/star/ucb/ContentCreationException.hpp>
32 #include <sfx2/app.hxx>
33 #include <sfx2/viewfrm.hxx>
34 #include <sfx2/bindings.hxx>
35 #include <galobj.hxx>
36 #include <svx/svxids.hrc>
37 #include <svx/gallery1.hxx>
38 #include <svx/galtheme.hxx>
39 #include <svx/galmisc.hxx>
40 #include <svx/galctrl.hxx>
41 #include <galbrws1.hxx>
42 #include <svx/strings.hrc>
43 #include <algorithm>
44 #include <svx/dialmgr.hxx>
45 #include <svx/galleryitem.hxx>
46 #include <comphelper/dispatchcommand.hxx>
47 #include <comphelper/propertyvalue.hxx>
48 #include <com/sun/star/beans/PropertyValue.hpp>
49 #include <comphelper/processfactory.hxx>
50 #include <com/sun/star/frame/FrameSearchFlag.hpp>
51 #include <com/sun/star/frame/XDispatchProvider.hpp>
52 #include <com/sun/star/frame/XFrame.hpp>
53 #include <com/sun/star/gallery/GalleryItemType.hpp>
54 #include <com/sun/star/graphic/XGraphic.hpp>
55 #include <com/sun/star/lang/XComponent.hpp>
56 #include <com/sun/star/style/GraphicLocation.hpp>
57 #include <svx/svxdlg.hxx>
58 #include <memory>
59 #include <bitmaps.hlst>
60 #include <osl/diagnose.h>
61 #include <o3tl/string_view.hxx>
63 using namespace ::com::sun::star;
65 namespace
68 struct DispatchInfo
70 css::util::URL TargetURL;
71 css::uno::Sequence< css::beans::PropertyValue > Arguments;
72 css::uno::Reference< css::frame::XDispatch > Dispatch;
75 struct CommandInfo
77 css::util::URL URL;
78 css::uno::Reference< css::frame::XDispatch > Dispatch;
80 explicit CommandInfo( const OUString &rURL )
82 URL.Complete = rURL;
86 class GalleryThemePopup : public ::cppu::WeakImplHelper< css::frame::XStatusListener >
88 private:
89 const GalleryTheme* mpTheme;
90 sal_uInt32 mnObjectPos;
91 bool mbPreview;
92 std::unique_ptr<weld::Builder> mxBuilder;
93 std::unique_ptr<weld::Menu> mxPopupMenu;
94 std::unique_ptr<weld::Menu> mxBackgroundPopup;
95 GalleryBrowser1* mpBrowser;
97 typedef std::map< int, CommandInfo > CommandInfoMap;
98 CommandInfoMap m_aCommandInfo;
100 static void Execute( const CommandInfo &rCmdInfo,
101 const css::uno::Sequence< css::beans::PropertyValue > &rArguments );
103 void MenuSelectHdl(std::u16string_view rIdent);
104 void BackgroundMenuSelectHdl(sal_uInt16 nId);
105 public:
106 GalleryThemePopup(weld::Widget* pParent,
107 const GalleryTheme* pTheme,
108 sal_uInt32 nObjectPos,
109 bool bPreview,
110 GalleryBrowser1* pBrowser);
112 void ExecutePopup(weld::Widget* pParent, const ::Point &rPos);
114 virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent &rEvent) override;
115 virtual void SAL_CALL disposing( const css::lang::EventObject &rSource) override;
120 GalleryBrowser1::GalleryBrowser1(
121 weld::Builder& rBuilder,
122 Gallery* pGallery)//,
123 //std::function<void ()> aThemeSelectionHandler)
125 mxNewTheme(rBuilder.weld_button(u"insert"_ustr)),
126 mxThemes(rBuilder.weld_tree_view(u"themelist"_ustr)),
127 mxMoreGalleries(rBuilder.weld_button(u"btnMoreGalleries"_ustr)),
128 mpGallery ( pGallery ),
129 mpExchangeData ( new ExchangeData ),
130 aImgNormal ( RID_SVXBMP_THEME_NORMAL ),
131 aImgDefault ( RID_SVXBMP_THEME_DEFAULT ),
132 aImgReadOnly ( RID_SVXBMP_THEME_READONLY )
133 //maThemeSelectionHandler(std::move(aThemeSelectionHandler))
134 , mpCurTheme(nullptr)
135 , mxIconView(new GalleryIconView(this, rBuilder.weld_scrolled_window(u"galleryscroll"_ustr, true)))
136 , mxIconViewWin(new weld::CustomWeld(rBuilder, u"gallery"_ustr, *mxIconView))
137 , mxListView(rBuilder.weld_tree_view(u"gallerylist"_ustr))
138 , mxPreview(new GalleryPreview(this, rBuilder.weld_scrolled_window(u"previewscroll"_ustr)))
139 , mxPreviewWin(new weld::CustomWeld(rBuilder, u"preview"_ustr, *mxPreview))
140 , mxIconButton(rBuilder.weld_toggle_button(u"icon"_ustr))
141 , mxListButton(rBuilder.weld_toggle_button(u"list"_ustr))
142 , mxSearchField(rBuilder.weld_entry(u"search"_ustr))
143 , mxInfoBar(rBuilder.weld_label(u"label"_ustr))
144 , maPreviewSize(28, 28)
145 , mnCurActionPos ( 0xffffffff )
146 , meMode ( GALLERYBROWSERMODE_NONE )
147 , meLastMode ( GALLERYBROWSERMODE_NONE )
148 , m_aCharacterClassficator( ::comphelper::getProcessComponentContext(), SvtSysLocale().GetLanguageTag() )
150 mxNewTheme->connect_clicked( LINK( this, GalleryBrowser1, ClickNewThemeHdl ) );
152 mxThemes->make_sorted();
153 mxThemes->connect_selection_changed(LINK(this, GalleryBrowser1, SelectThemeHdl));
154 mxThemes->connect_popup_menu(LINK(this, GalleryBrowser1, PopupMenuHdl1));
155 mxThemes->connect_key_press(LINK(this, GalleryBrowser1, KeyInputHdl1));
156 mxThemes->set_size_request(-1, mxThemes->get_height_rows(6));
158 mxMoreGalleries->connect_clicked(LINK(this, GalleryBrowser1, OnMoreGalleriesClick));
160 // disable creation of new themes if a writable directory is not available
161 if( mpGallery->GetUserURL().GetProtocol() == INetProtocol::NotValid )
162 mxNewTheme->set_sensitive(false);
164 StartListening( *mpGallery );
166 for (size_t i = 0, nCount = mpGallery->GetThemeCount(); i < nCount; ++i)
167 ImplInsertThemeEntry( mpGallery->GetThemeInfo( i ) );
169 m_xContext.set( ::comphelper::getProcessComponentContext() );
171 int nHeight = mxListView->get_height_rows(10);
172 mxListView->set_size_request(-1, nHeight);
173 mxIconView->set_size_request(-1, nHeight);
175 m_xTransformer.set(
176 m_xContext->getServiceManager()->createInstanceWithContext(
177 u"com.sun.star.util.URLTransformer"_ustr, m_xContext ),
178 css::uno::UNO_QUERY );
180 mxIconButton->connect_toggled( LINK( this, GalleryBrowser1, SelectTbxHdl ) );
181 mxListButton->connect_toggled( LINK( this, GalleryBrowser1, SelectTbxHdl ) );
183 mxIconView->SetSelectHdl( LINK( this, GalleryBrowser1, SelectObjectValueSetHdl ) );
184 mxListView->connect_visible_range_changed(LINK(this, GalleryBrowser1, VisRowsScrolledHdl));
185 mxListView->connect_size_allocate(LINK(this, GalleryBrowser1, SizeAllocHdl));
186 mxListView->connect_selection_changed(LINK(this, GalleryBrowser1, SelectObjectHdl));
187 mxListView->connect_popup_menu(LINK(this, GalleryBrowser1, PopupMenuHdl2));
188 mxListView->connect_key_press(LINK(this, GalleryBrowser1, KeyInputHdl2));
189 mxListView->connect_row_activated(LINK(this, GalleryBrowser1, RowActivatedHdl));
190 mxDragDropTargetHelper.reset(new GalleryDragDrop(this, mxListView->get_drop_target()));
191 mxListView->connect_drag_begin(LINK(this, GalleryBrowser1, DragBeginHdl));
192 mxSearchField->connect_changed( LINK( this, GalleryBrowser1, SearchHdl));
194 SetMode( ( GALLERYBROWSERMODE_PREVIEW != GalleryBrowser1::meInitMode ) ? GalleryBrowser1::meInitMode : GALLERYBROWSERMODE_ICON );
196 FillThemeEntries();
199 GalleryBrowser1::~GalleryBrowser1()
201 EndListening( *mpGallery );
202 mpExchangeData.reset();
203 if (mpCurTheme)
204 mpGallery->ReleaseTheme( mpCurTheme, *this );
207 void GalleryBrowser1::ImplInsertThemeEntry( const GalleryThemeEntry* pEntry )
209 static const bool bShowHiddenThemes = ( getenv( "GALLERY_SHOW_HIDDEN_THEMES" ) != nullptr );
211 if( !(pEntry && ( !pEntry->IsHidden() || bShowHiddenThemes )) )
212 return;
214 const OUString* pImage;
216 if( pEntry->IsReadOnly() )
217 pImage = &aImgReadOnly;
218 else if( pEntry->IsDefault() )
219 pImage = &aImgDefault;
220 else
221 pImage = &aImgNormal;
223 mxThemes->append(u""_ustr, pEntry->GetThemeName(), *pImage);
226 void GalleryBrowser1::ImplFillExchangeData(const GalleryTheme& rThm, ExchangeData& rData)
228 rData.pTheme = const_cast<GalleryTheme*>(&rThm);
229 rData.aEditedTitle = rThm.GetName();
233 DateTime aDateTime(rThm.getModificationDate());
235 rData.aThemeChangeDate = aDateTime;
236 rData.aThemeChangeTime = aDateTime;
238 catch( const ucb::ContentCreationException& )
241 catch( const uno::RuntimeException& )
244 catch( const uno::Exception& )
249 void GalleryBrowser1::ImplGetExecuteVector(std::vector<OUString>& o_aExec)
251 GalleryTheme* pTheme = mpGallery->AcquireTheme( GetSelectedTheme(), maLocalListener );
253 if( !pTheme )
254 return;
256 bool bUpdateAllowed, bRenameAllowed, bRemoveAllowed;
257 static const bool bIdDialog = ( getenv( "GALLERY_ENABLE_ID_DIALOG" ) != nullptr );
259 if( pTheme->IsReadOnly() )
260 bUpdateAllowed = bRenameAllowed = bRemoveAllowed = false;
261 else if( pTheme->IsDefault() )
263 bUpdateAllowed = bRenameAllowed = true;
264 bRemoveAllowed = false;
266 else
267 bUpdateAllowed = bRenameAllowed = bRemoveAllowed = true;
269 if( bUpdateAllowed && pTheme->GetObjectCount() )
270 o_aExec.emplace_back("update");
272 if( bRenameAllowed )
273 o_aExec.emplace_back("rename");
275 if( bRemoveAllowed )
276 o_aExec.emplace_back("delete");
278 if( bIdDialog && !pTheme->IsReadOnly() )
279 o_aExec.emplace_back("assign");
281 o_aExec.emplace_back("properties");
283 mpGallery->ReleaseTheme( pTheme, maLocalListener );
286 void GalleryBrowser1::ImplGalleryThemeProperties( std::u16string_view rThemeName, bool bCreateNew )
288 DBG_ASSERT(!mpThemePropsDlgItemSet, "mpThemePropsDlgItemSet already set!");
289 mpThemePropsDlgItemSet.reset(new SfxItemSet( SfxGetpApp()->GetPool() ));
290 GalleryTheme* pTheme = mpGallery->AcquireTheme( rThemeName, maLocalListener );
291 if (!pTheme)
293 SAL_WARN("svx", "failed to acquire theme: " << OUString(rThemeName));
294 return;
297 ImplFillExchangeData(*pTheme, *mpExchangeData);
299 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
300 VclPtr<VclAbstractDialog> xThemePropertiesDialog = pFact->CreateGalleryThemePropertiesDialog(mxThemes.get(), mpExchangeData.get(), mpThemePropsDlgItemSet.get());
302 if ( bCreateNew )
304 xThemePropertiesDialog->StartExecuteAsync([xThemePropertiesDialog, this](sal_Int32 nResult){
305 EndNewThemePropertiesDlgHdl(nResult);
306 xThemePropertiesDialog->disposeOnce();
309 else
311 xThemePropertiesDialog->StartExecuteAsync([xThemePropertiesDialog, this](sal_Int32 nResult){
312 EndThemePropertiesDlgHdl(nResult);
313 xThemePropertiesDialog->disposeOnce();
318 void GalleryBrowser1::ImplEndGalleryThemeProperties(bool bCreateNew, sal_Int32 nRet)
320 if( nRet == RET_OK )
322 OUString aName( mpExchangeData->pTheme->GetName() );
324 if( !mpExchangeData->aEditedTitle.isEmpty() && aName != mpExchangeData->aEditedTitle )
326 OUString aTitle( mpExchangeData->aEditedTitle );
327 sal_uInt16 nCount = 0;
329 while( mpGallery->HasTheme( aTitle ) && ( nCount++ < 16000 ) )
331 aTitle = mpExchangeData->aEditedTitle + " " + OUString::number( nCount );
334 mpGallery->RenameTheme( aName, aTitle );
337 if ( bCreateNew )
339 mxThemes->select_text( mpExchangeData->pTheme->GetName() );
340 SelectThemeHdl( *mxThemes );
344 OUString aThemeName( mpExchangeData->pTheme->GetName() );
345 mpGallery->ReleaseTheme( mpExchangeData->pTheme, maLocalListener );
347 if ( bCreateNew && ( nRet != RET_OK ) )
349 mpGallery->RemoveTheme( aThemeName );
353 void GalleryBrowser1::EndNewThemePropertiesDlgHdl(sal_Int32 nResult)
355 ImplEndGalleryThemeProperties(true, nResult);
358 void GalleryBrowser1::EndThemePropertiesDlgHdl(sal_Int32 nResult)
360 ImplEndGalleryThemeProperties(false, nResult);
363 void GalleryBrowser1::ImplExecute(std::u16string_view rIdent)
365 if (rIdent == u"update")
367 if (GalleryTheme* pTheme = mpGallery->AcquireTheme( GetSelectedTheme(), maLocalListener ))
369 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
370 ScopedVclPtr<VclAbstractDialog> aActualizeProgress(pFact->CreateActualizeProgressDialog(mxThemes.get(), pTheme));
372 aActualizeProgress->Execute();
373 mpGallery->ReleaseTheme( pTheme, maLocalListener );
376 else if (rIdent == u"delete")
378 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(mxThemes.get(), u"svx/ui/querydeletethemedialog.ui"_ustr));
379 std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog(u"QueryDeleteThemeDialog"_ustr));
380 if (xQuery->run() == RET_YES)
381 mpGallery->RemoveTheme( mxThemes->get_selected_text() );
383 else if (rIdent == u"rename")
385 if (GalleryTheme* pTheme = mpGallery->AcquireTheme(GetSelectedTheme(), maLocalListener))
387 const OUString aOldName( pTheme->GetName() );
389 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
390 ScopedVclPtr<AbstractTitleDialog> aDlg(pFact->CreateTitleDialog(mxThemes.get(), aOldName));
392 if( aDlg->Execute() == RET_OK )
394 const OUString aNewName( aDlg->GetTitle() );
396 if( !aNewName.isEmpty() && ( aNewName != aOldName ) )
398 OUString aName( aNewName );
399 sal_uInt16 nCount = 0;
401 while( mpGallery->HasTheme( aName ) && ( nCount++ < 16000 ) )
403 aName = aNewName + " " + OUString::number( nCount );
406 mpGallery->RenameTheme( aOldName, aName );
409 mpGallery->ReleaseTheme( pTheme, maLocalListener );
412 else if (rIdent == u"assign")
414 if (GalleryTheme* pTheme = mpGallery->AcquireTheme( GetSelectedTheme(), maLocalListener ))
416 if (!pTheme->IsReadOnly())
418 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
419 ScopedVclPtr<AbstractGalleryIdDialog> aDlg(pFact->CreateGalleryIdDialog(mxThemes.get(), pTheme));
420 if( aDlg->Execute() == RET_OK )
421 pTheme->SetId( aDlg->GetId(), true );
424 mpGallery->ReleaseTheme( pTheme, maLocalListener );
427 else if (rIdent == u"properties")
429 ImplGalleryThemeProperties( GetSelectedTheme(), false );
433 //TODO Duplicate method
434 void GalleryBrowser1::Notify( SfxBroadcaster&, const SfxHint& rHint )
436 const GalleryHint& rGalleryHint = static_cast<const GalleryHint&>(rHint);
438 switch( rGalleryHint.GetType() )
440 case GalleryHintType::THEME_CREATED:
441 ImplInsertThemeEntry( mpGallery->GetThemeInfo( rGalleryHint.GetThemeName() ) );
442 break;
444 case GalleryHintType::THEME_RENAMED:
446 const sal_Int32 nCurSelectPos = mxThemes->get_selected_index();
447 const sal_Int32 nRenameEntryPos = mxThemes->find_text( rGalleryHint.GetThemeName() );
449 mxThemes->remove_text( rGalleryHint.GetThemeName() );
450 ImplInsertThemeEntry( mpGallery->GetThemeInfo( rGalleryHint.GetStringData() ) );
452 if( nCurSelectPos == nRenameEntryPos )
454 mxThemes->select_text( rGalleryHint.GetStringData() );
455 SelectThemeHdl( *mxThemes );
458 break;
460 case GalleryHintType::THEME_REMOVED:
462 mxThemes->remove_text( rGalleryHint.GetThemeName() );
464 break;
466 case GalleryHintType::CLOSE_THEME:
468 const sal_Int32 nCurSelectPos = mxThemes->get_selected_index();
469 const sal_Int32 nCloseEntryPos = mxThemes->find_text( rGalleryHint.GetThemeName() );
471 if( nCurSelectPos == nCloseEntryPos )
473 if( nCurSelectPos < ( mxThemes->n_children() - 1 ) )
474 mxThemes->select( nCurSelectPos + 1 );
475 else if( nCurSelectPos )
476 mxThemes->select( nCurSelectPos - 1 );
477 else
478 mxThemes->select(-1);
480 SelectThemeHdl( *mxThemes );
483 break;
485 case GalleryHintType::THEME_UPDATEVIEW:
487 if( GALLERYBROWSERMODE_PREVIEW == GetMode() )
488 SetMode( meLastMode );
490 ImplUpdateViews( reinterpret_cast<size_t>(rGalleryHint.GetData1()) + 1 );
492 break;
494 default:
495 break;
500 IMPL_STATIC_LINK_NOARG( GalleryBrowser1, OnMoreGalleriesClick, weld::Button&, void)
502 css::uno::Sequence<css::beans::PropertyValue> aArgs{
503 comphelper::makePropertyValue(u"AdditionsTag"_ustr, u"Gallery"_ustr)
505 comphelper::dispatchCommand(u".uno:AdditionsDialog"_ustr, aArgs);
508 IMPL_LINK(GalleryBrowser1, KeyInputHdl1, const KeyEvent&, rKEvt, bool)
510 bool bRet = false;
512 std::vector<OUString> aExecVector;
513 ImplGetExecuteVector(aExecVector);
514 OUString sExecuteIdent;
515 bool bMod1 = rKEvt.GetKeyCode().IsMod1();
517 switch( rKEvt.GetKeyCode().GetCode() )
519 case KEY_INSERT:
520 ClickNewThemeHdl(*mxNewTheme);
521 break;
523 case KEY_I:
525 if( bMod1 )
526 ClickNewThemeHdl(*mxNewTheme);
528 break;
530 case KEY_U:
532 if( bMod1 )
533 sExecuteIdent = "update";
535 break;
537 case KEY_DELETE:
538 sExecuteIdent = "delete";
539 break;
541 case KEY_D:
543 if( bMod1 )
544 sExecuteIdent = "delete";
546 break;
548 case KEY_R:
550 if( bMod1 )
551 sExecuteIdent = "rename";
553 break;
555 case KEY_RETURN:
557 if( bMod1 )
558 sExecuteIdent = "properties";
560 break;
563 if (!sExecuteIdent.isEmpty() && (std::find( aExecVector.begin(), aExecVector.end(), sExecuteIdent) != aExecVector.end()))
565 ImplExecute(sExecuteIdent);
566 bRet = true;
569 return bRet;
572 IMPL_LINK(GalleryBrowser1, PopupMenuHdl1, const CommandEvent&, rCEvt, bool)
574 if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
575 return false;
577 std::vector<OUString> aExecVector;
578 ImplGetExecuteVector(aExecVector);
580 if (aExecVector.empty())
581 return true;
583 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(mxThemes.get(), u"svx/ui/gallerymenu1.ui"_ustr));
584 std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu(u"menu"_ustr));
586 xMenu->set_visible(u"update"_ustr, std::find( aExecVector.begin(), aExecVector.end(), "update" ) != aExecVector.end());
587 xMenu->set_visible(u"rename"_ustr, std::find( aExecVector.begin(), aExecVector.end(), "rename" ) != aExecVector.end());
588 xMenu->set_visible(u"delete"_ustr, std::find( aExecVector.begin(), aExecVector.end(), "delete" ) != aExecVector.end());
589 xMenu->set_visible(u"assign"_ustr, std::find( aExecVector.begin(), aExecVector.end(), "assign" ) != aExecVector.end());
590 xMenu->set_visible(u"properties"_ustr, std::find( aExecVector.begin(), aExecVector.end(), "properties" ) != aExecVector.end());
592 OUString sCommand(xMenu->popup_at_rect(mxThemes.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1))));
593 ImplExecute(sCommand);
595 return true;
598 IMPL_LINK_NOARG(GalleryBrowser1, SelectThemeHdl, weld::TreeView&, void)
600 SelectTheme(GetSelectedTheme());
603 IMPL_LINK_NOARG(GalleryBrowser1, ClickNewThemeHdl, weld::Button&, void)
605 OUString aNewTheme( SvxResId(RID_SVXSTR_GALLERY_NEWTHEME) );
606 OUString aName( aNewTheme );
607 sal_uInt16 nCount = 0;
609 while( mpGallery->HasTheme( aName ) && ( nCount++ < 16000 ) )
611 aName = aNewTheme + " " + OUString::number( nCount );
614 if( !mpGallery->HasTheme( aName ) && mpGallery->CreateTheme( aName ) )
616 ImplGalleryThemeProperties( aName, true );
620 GalleryBrowserMode GalleryBrowser1::meInitMode = GALLERYBROWSERMODE_ICON;
622 IMPL_STATIC_LINK( GalleryBrowser1, AsyncDispatch_Impl, void*, p, void )
624 DispatchInfo* pDispatchInfo = static_cast<DispatchInfo*>(p);
625 if ( pDispatchInfo && pDispatchInfo->Dispatch.is() )
629 pDispatchInfo->Dispatch->dispatch( pDispatchInfo->TargetURL,
630 pDispatchInfo->Arguments );
632 catch ( const css::uno::Exception& )
637 delete pDispatchInfo;
640 IMPL_LINK(GalleryBrowser1, PopupMenuHdl2, const CommandEvent&, rCEvt, bool)
642 if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
643 return false;
644 ShowContextMenu(rCEvt);
645 return true;
648 IMPL_LINK(GalleryBrowser1, KeyInputHdl2, const KeyEvent&, rKEvt, bool)
650 return KeyInput(rKEvt);
653 IMPL_LINK_NOARG(GalleryBrowser1, RowActivatedHdl, weld::TreeView&, bool)
655 TogglePreview();
656 return true;
659 sal_Int8 GalleryBrowser1::AcceptDrop( const DropTargetHelper& rTarget )
661 sal_Int8 nRet = DND_ACTION_NONE;
663 if( mpCurTheme && !mpCurTheme->IsReadOnly() )
665 if( !mpCurTheme->IsDragging() )
667 if( rTarget.IsDropFormatSupported( SotClipboardFormatId::DRAWING ) ||
668 rTarget.IsDropFormatSupported( SotClipboardFormatId::FILE_LIST ) ||
669 rTarget.IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE ) ||
670 rTarget.IsDropFormatSupported( SotClipboardFormatId::SVXB ) ||
671 rTarget.IsDropFormatSupported( SotClipboardFormatId::GDIMETAFILE ) ||
672 rTarget.IsDropFormatSupported( SotClipboardFormatId::BITMAP ) )
674 nRet = DND_ACTION_COPY;
677 else
678 nRet = DND_ACTION_COPY;
681 return nRet;
684 sal_Int8 GalleryBrowser1::ExecuteDrop( const ExecuteDropEvent& rEvt )
686 sal_Int8 nRet = DND_ACTION_NONE;
688 if( mpCurTheme )
690 Point aSelPos;
691 const sal_uInt32 nItemId = ImplGetSelectedItemId( &rEvt.maPosPixel, aSelPos );
692 const sal_uInt32 nInsertPos = (nItemId ? (nItemId - 1) : mpCurTheme->GetObjectCount());
694 if( mpCurTheme->IsDragging() )
695 mpCurTheme->ChangeObjectPos( mpCurTheme->GetDragPos(), nInsertPos );
696 else
697 nRet = mpCurTheme->InsertTransferable( rEvt.maDropEvent.Transferable, nInsertPos ) ? 1 : 0;
700 return nRet;
703 bool GalleryBrowser1::StartDrag()
705 if (!mpCurTheme)
706 return true;
707 return m_xHelper->StartDrag();
710 IMPL_LINK(GalleryBrowser1, DragBeginHdl, bool&, rUnsetDragIcon, bool)
712 rUnsetDragIcon = false;
713 return StartDrag();
716 void GalleryBrowser1::TogglePreview()
718 SetMode( ( GALLERYBROWSERMODE_PREVIEW != GetMode() ) ? GALLERYBROWSERMODE_PREVIEW : meLastMode );
719 GetViewWindow()->grab_focus();
722 bool GalleryBrowser1::ShowContextMenu(const CommandEvent& rCEvt)
724 Point aMousePos = rCEvt.GetMousePosPixel();
725 Point aSelPos;
726 const sal_uInt32 nItemId = ImplGetSelectedItemId( rCEvt.IsMouseEvent() ? &aMousePos : nullptr, aSelPos );
728 if( !(mpCurTheme && nItemId && ( nItemId <= mpCurTheme->GetObjectCount() )) )
729 return false;
731 ImplSelectItemId( nItemId );
733 css::uno::Reference< css::frame::XFrame > xFrame( GetFrame() );
734 if ( !xFrame.is() )
735 return false;
737 weld::Widget* pParent = GetViewWindow();
738 mnCurActionPos = nItemId - 1;
739 rtl::Reference< GalleryThemePopup > xPopup(
740 new GalleryThemePopup(
741 pParent,
742 mpCurTheme,
743 mnCurActionPos,
744 GALLERYBROWSERMODE_PREVIEW == GetMode(),
745 this ) );
746 xPopup->ExecutePopup(pParent, aSelPos);
747 return true;
750 bool GalleryBrowser1::ViewBoxHasFocus() const
752 return mxIconButton->has_focus() || mxListButton->has_focus();
755 bool GalleryBrowser1::KeyInput(const KeyEvent& rKEvt)
757 Point aSelPos;
758 const sal_uInt32 nItemId = ImplGetSelectedItemId( nullptr, aSelPos );
759 bool bRet = false;
761 if (!ViewBoxHasFocus() && nItemId && mpCurTheme)
763 OUString sExecuteIdent;
764 INetURLObject aURL;
766 mpCurTheme->GetURL( nItemId - 1, aURL );
768 const bool bValidURL = ( aURL.GetProtocol() != INetProtocol::NotValid );
769 bool bPreview = bValidURL;
770 bool bDelete = false;
771 bool bTitle = false;
773 if( !mpCurTheme->IsReadOnly() && mpCurTheme->GetObjectCount() )
775 bDelete = ( GALLERYBROWSERMODE_PREVIEW != GetMode() );
776 bTitle = true;
779 switch( rKEvt.GetKeyCode().GetCode() )
781 case KEY_SPACE:
782 case KEY_RETURN:
783 case KEY_P:
785 if( bPreview )
787 TogglePreview();
788 bRet = true;
791 break;
793 case KEY_INSERT:
794 case KEY_I:
796 // Inserting a gallery item in the document must be dispatched
797 if( bValidURL )
799 DispatchAdd(css::uno::Reference<css::frame::XDispatch>(), css::util::URL());
800 return true;
803 break;
805 case KEY_DELETE:
806 case KEY_D:
808 if( bDelete )
809 sExecuteIdent = "delete";
811 break;
813 case KEY_T:
815 if( bTitle )
816 sExecuteIdent = "title";
818 break;
820 default:
821 break;
824 if (!sExecuteIdent.isEmpty())
826 Execute(sExecuteIdent);
827 bRet = true;
831 return bRet;
834 void GalleryBrowser1::SelectTheme( std::u16string_view rThemeName )
836 if( mpCurTheme )
837 mpGallery->ReleaseTheme( mpCurTheme, *this );
839 if (rThemeName.empty())
841 mxIconButton->set_sensitive(false);
842 mxListButton->set_sensitive(false);
843 mxListView->clear();
844 mxIconView->Clear();
845 mpCurTheme = nullptr;
847 else
849 mpCurTheme = mpGallery->AcquireTheme( rThemeName, *this );
851 m_xHelper.set(new GalleryTransferable(mpCurTheme, 0, true));
852 rtl::Reference<TransferDataContainer> xHelper(m_xHelper);
853 mxListView->enable_drag_source(xHelper, DND_ACTION_COPY | DND_ACTION_LINK);
854 mxIconView->SetDragDataTransferable(xHelper, DND_ACTION_COPY | DND_ACTION_LINK);
855 mxPreview->SetDragDataTransferable(xHelper, DND_ACTION_COPY | DND_ACTION_LINK);
857 mxIconView->SetTheme(mpCurTheme);
858 mxPreview->SetTheme(mpCurTheme);
860 if( GALLERYBROWSERMODE_PREVIEW == GetMode() )
861 meMode = meLastMode;
863 ImplUpdateViews( 1 );
865 bool bIconMode = (GALLERYBROWSERMODE_ICON == GetMode());
866 mxIconButton->set_sensitive(true);
867 mxListButton->set_sensitive(true);
868 mxIconButton->set_active(bIconMode);
869 mxListButton->set_active(!bIconMode);
873 void GalleryBrowser1::SetMode( GalleryBrowserMode eMode )
875 if( GetMode() == eMode )
876 return;
878 meLastMode = GetMode();
880 switch( eMode )
882 case GALLERYBROWSERMODE_ICON:
884 mxListView->hide();
886 mxPreview->Hide();
887 mxPreview->SetGraphic( Graphic() );
888 GalleryPreview::PreviewMedia( INetURLObject() );
890 mxIconView->Show();
892 mxIconButton->set_sensitive(true);
893 mxListButton->set_sensitive(true);
895 mxIconButton->set_active(true);
896 mxListButton->set_active(false);
898 break;
900 case GALLERYBROWSERMODE_LIST:
902 mxIconView->Hide();
904 mxPreview->Hide();
905 mxPreview->SetGraphic( Graphic() );
906 GalleryPreview::PreviewMedia( INetURLObject() );
908 mxListView->show();
909 UpdateRows(true);
911 mxIconButton->set_sensitive(true);
912 mxListButton->set_sensitive(true);
914 mxIconButton->set_active(false);
915 mxListButton->set_active(true);
917 break;
919 case GALLERYBROWSERMODE_PREVIEW:
921 Graphic aGraphic;
922 Point aSelPos;
923 const sal_uInt32 nItemId = ImplGetSelectedItemId( nullptr, aSelPos );
925 if( nItemId )
927 const sal_uInt32 nPos = nItemId - 1;
929 mxIconView->Hide();
930 mxListView->hide();
932 if( mpCurTheme )
933 mpCurTheme->GetGraphic( nPos, aGraphic );
935 mxPreview->SetGraphic( aGraphic );
936 mxPreview->Show();
938 if( mpCurTheme && mpCurTheme->GetObjectKind( nPos ) == SgaObjKind::Sound )
939 GalleryPreview::PreviewMedia( mpCurTheme->GetObjectURL( nPos ) );
941 mxIconButton->set_sensitive(false);
942 mxListButton->set_sensitive(false);
945 break;
947 default:
948 break;
951 GalleryBrowser1::meInitMode = meMode = eMode;
954 weld::Widget* GalleryBrowser1::GetViewWindow() const
956 weld::Widget* pRet;
958 switch( GetMode() )
960 case GALLERYBROWSERMODE_LIST: pRet = mxListView.get(); break;
961 case GALLERYBROWSERMODE_PREVIEW: pRet = mxPreview->GetDrawingArea(); break;
963 default:
964 pRet = mxIconView->GetDrawingArea();
965 break;
968 return pRet;
971 void GalleryBrowser1::Travel( GalleryBrowserTravel eTravel )
973 if( !mpCurTheme )
974 return;
976 Point aSelPos;
977 const sal_uInt32 nItemId = ImplGetSelectedItemId( nullptr, aSelPos );
979 if( !nItemId )
980 return;
982 sal_uInt32 nNewItemId = nItemId;
984 switch( eTravel )
986 case GalleryBrowserTravel::First: nNewItemId = 1; break;
987 case GalleryBrowserTravel::Last: nNewItemId = mpCurTheme->GetObjectCount(); break;
988 case GalleryBrowserTravel::Previous: nNewItemId--; break;
989 case GalleryBrowserTravel::Next: nNewItemId++; break;
990 default:
991 break;
994 if( nNewItemId < 1 )
995 nNewItemId = 1;
996 else if( nNewItemId > mpCurTheme->GetObjectCount() )
997 nNewItemId = mpCurTheme->GetObjectCount();
999 if( nNewItemId == nItemId )
1000 return;
1002 ImplSelectItemId( nNewItemId );
1003 ImplUpdateInfoBar();
1005 if( GALLERYBROWSERMODE_PREVIEW != GetMode() )
1006 return;
1008 Graphic aGraphic;
1009 const sal_uInt32 nPos = nNewItemId - 1;
1011 mpCurTheme->GetGraphic( nPos, aGraphic );
1012 mxPreview->SetGraphic( aGraphic );
1014 if( SgaObjKind::Sound == mpCurTheme->GetObjectKind( nPos ) )
1015 GalleryPreview::PreviewMedia( mpCurTheme->GetObjectURL( nPos ) );
1017 mxPreview->Invalidate();
1020 void GalleryBrowser1::ImplUpdateViews( sal_uInt16 nSelectionId )
1022 mxIconView->Hide();
1023 mxListView->hide();
1024 mxPreview->Hide();
1026 mxIconView->Clear();
1027 mxListView->clear();
1029 if( mpCurTheme )
1031 const int nAlwaysUpToDate = 15;
1033 mxListView->freeze();
1034 OUString aThemeName = mpCurTheme->GetName();
1035 sal_Int32 inserted = 0;
1036 for (GalleryThemeEntries::const_iterator aFoundIter = maFoundThemeEntries.begin(); aFoundIter != maFoundThemeEntries.end(); ++aFoundIter)
1038 if (aFoundIter->maThemeName == aThemeName)
1040 mxIconView->InsertItem(aFoundIter->mnIdInTheme + 1); // skip reserved id 0
1041 mxListView->append(OUString::number(aFoundIter->mnIdInTheme),u""_ustr); // create on-demand in VisRowsScrolledHdl
1043 if (inserted == nAlwaysUpToDate) // fill in the first block
1044 UpdateRows(false);
1045 ++inserted;
1049 /* sal_uInt32 nCount = mpCurTheme->GetObjectCount();
1050 for (sal_uInt32 i = 0; i < nCount; ++i)
1052 mxIconView->InsertItem(i + 1); // skip reserved id 0
1053 mxListView->append(OUString::number(i), ""); // create on-demand in VisRowsScrolledHdl
1055 if (i == nAlwaysUpToDate) // fill in the first block
1056 UpdateRows(false);
1059 if (inserted < nAlwaysUpToDate) // if less than block size, fill in all of them
1060 UpdateRows(false);
1062 mxListView->thaw();
1064 ImplSelectItemId( std::min<sal_uInt16>( nSelectionId, mpCurTheme->GetObjectCount() ) );
1067 switch( GetMode() )
1069 case GALLERYBROWSERMODE_ICON: mxIconView->Show(); break;
1070 case GALLERYBROWSERMODE_LIST:
1071 mxListView->show();
1072 UpdateRows(true);
1073 break;
1074 case GALLERYBROWSERMODE_PREVIEW: mxPreview->Show(); break;
1076 default:
1077 break;
1080 ImplUpdateInfoBar();
1083 void GalleryBrowser1::UpdateRows(bool bVisibleOnly)
1085 auto lambda = [this](weld::TreeIter& rEntry){
1086 // id is non-null if the preview is pending creation
1087 OUString sId(mxListView->get_id(rEntry));
1088 if (sId.isEmpty())
1089 return false;
1091 // get the icon for the listview
1092 BitmapEx aBitmapEx;
1093 Size aPreparedSize;
1095 OUString sItemTextTitle;
1096 OUString sItemTextPath;
1098 sal_Int32 i = sId.toUInt32();
1099 mpCurTheme->GetPreviewBitmapExAndStrings(i, aBitmapEx, aPreparedSize, sItemTextTitle, sItemTextPath);
1101 bool bNeedToCreate(aBitmapEx.IsEmpty());
1102 if (!bNeedToCreate && (sItemTextTitle.isEmpty() || aPreparedSize != maPreviewSize))
1103 bNeedToCreate = true;
1105 if (bNeedToCreate)
1107 std::unique_ptr<SgaObject> xObj = mpCurTheme->AcquireObject(i);
1108 if (xObj)
1110 aBitmapEx = xObj->createPreviewBitmapEx(maPreviewSize);
1111 sItemTextTitle = GalleryBrowser1::GetItemText(*xObj, GalleryItemFlags::Title);
1112 sItemTextPath = GalleryBrowser1::GetItemText(*xObj, GalleryItemFlags::Path);
1114 mpCurTheme->SetPreviewBitmapExAndStrings(i, aBitmapEx, maPreviewSize, sItemTextTitle, sItemTextPath);
1118 ScopedVclPtr<VirtualDevice> xDev(mxListView->create_virtual_device());
1119 xDev->SetOutputSizePixel(maPreviewSize);
1121 if (!aBitmapEx.IsEmpty())
1123 const Size aBitmapExSizePixel(aBitmapEx.GetSizePixel());
1124 const Point aPos(
1125 ((maPreviewSize.Width() - aBitmapExSizePixel.Width()) >> 1),
1126 ((maPreviewSize.Height() - aBitmapExSizePixel.Height()) >> 1));
1128 if (aBitmapEx.IsAlpha())
1130 // draw checkered background
1131 GalleryIconView::drawTransparenceBackground(*xDev, aPos, aBitmapExSizePixel);
1134 xDev->DrawBitmapEx(aPos, aBitmapEx);
1137 mxListView->set_text(rEntry, sItemTextTitle);
1138 mxListView->set_image(rEntry, *xDev);
1139 mxListView->set_id(rEntry, OUString());
1141 return false;
1144 if (bVisibleOnly)
1146 // ensure all visible entries are up to date
1147 mxListView->visible_foreach(lambda);
1148 // and ensure all selected entries are up to date
1149 mxListView->selected_foreach(lambda);
1150 return;
1153 mxListView->all_foreach(lambda);
1156 IMPL_LINK_NOARG(GalleryBrowser1, VisRowsScrolledHdl, weld::TreeView&, void)
1158 UpdateRows(true);
1161 IMPL_LINK_NOARG(GalleryBrowser1, SizeAllocHdl, const Size&, void)
1163 UpdateRows(true);
1166 void GalleryBrowser1::ImplUpdateInfoBar()
1168 if (!mpCurTheme)
1169 return;
1170 mxInfoBar->set_label( mpCurTheme->GetName() );
1173 void GalleryBrowser1::ImplUpdateSelection()
1175 if (!mpCurTheme)
1176 return;
1177 auto nSelectedObject = (GALLERYBROWSERMODE_ICON == GetMode()) ? (mxIconView->GetSelectedItemId() - 1) : mxListView->get_selected_index();
1178 m_xHelper->SelectObject(nSelectedObject);
1181 sal_uInt32 GalleryBrowser1::ImplGetSelectedItemId( const Point* pSelPos, Point& rSelPos )
1183 sal_uInt32 nRet = 0;
1185 if( GALLERYBROWSERMODE_PREVIEW == GetMode() )
1187 nRet = ( ( GALLERYBROWSERMODE_ICON == meLastMode ) ? mxIconView->GetSelectedItemId() : ( mxListView->get_selected_index() + 1 ) );
1189 if( pSelPos )
1190 rSelPos = *pSelPos;
1191 else
1193 Size aOutputSizePixel(mxPreview->GetOutputSizePixel());
1194 rSelPos = Point( aOutputSizePixel.Width() >> 1, aOutputSizePixel.Height() >> 1 );
1197 else if (GALLERYBROWSERMODE_ICON == GetMode())
1199 if (pSelPos)
1201 nRet = mxIconView->GetItemId( *pSelPos );
1202 rSelPos = *pSelPos;
1204 else
1206 nRet = mxIconView->GetSelectedItemId();
1207 rSelPos = mxIconView->GetItemRect(nRet).Center();
1210 else
1212 std::unique_ptr<weld::TreeIter> xIter = mxListView->make_iterator();
1213 if( pSelPos )
1215 if (mxListView->get_dest_row_at_pos(*pSelPos, xIter.get(), false))
1216 nRet = mxListView->get_iter_index_in_parent(*xIter) + 1;
1217 rSelPos = *pSelPos;
1219 else
1221 if (mxListView->get_selected(xIter.get()))
1223 nRet = mxListView->get_iter_index_in_parent(*xIter) + 1;
1224 rSelPos = mxListView->get_row_area(*xIter).Center();
1229 if( nRet && ( !mpCurTheme || ( nRet > mpCurTheme->GetObjectCount() ) ) )
1231 nRet = 0;
1234 return nRet;
1237 void GalleryBrowser1::ImplSelectItemId(sal_uInt32 nItemId)
1239 if( nItemId )
1241 mxIconView->SelectItem(nItemId);
1242 mxListView->select( nItemId - 1 );
1243 ImplUpdateSelection();
1247 css::uno::Reference< css::frame::XFrame >
1248 GalleryBrowser1::GetFrame()
1250 css::uno::Reference< css::frame::XFrame > xFrame;
1251 SfxViewFrame* pCurrentViewFrame = SfxViewFrame::Current();
1252 if ( pCurrentViewFrame )
1254 SfxBindings& rBindings = pCurrentViewFrame->GetBindings();
1255 xFrame.set( rBindings.GetActiveFrame() );
1258 return xFrame;
1261 void GalleryBrowser1::DispatchAdd(
1262 const css::uno::Reference< css::frame::XDispatch > &rxDispatch,
1263 const css::util::URL &rURL)
1265 Point aSelPos;
1266 const sal_uInt32 nItemId = ImplGetSelectedItemId( nullptr, aSelPos );
1268 if( !mpCurTheme || !nItemId )
1269 return;
1271 mnCurActionPos = nItemId - 1;
1273 css::uno::Reference< css::frame::XDispatch > xDispatch( rxDispatch );
1274 css::util::URL aURL = rURL;
1276 if ( !xDispatch.is() )
1278 css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider(
1279 GetFrame(), css::uno::UNO_QUERY );
1280 if ( !xDispatchProvider.is() || !m_xTransformer.is() )
1281 return;
1283 aURL.Complete = ".uno:InsertGalleryPic";
1284 m_xTransformer->parseStrict( aURL );
1285 xDispatch = xDispatchProvider->queryDispatch(
1286 aURL,
1287 u"_self"_ustr,
1288 css::frame::FrameSearchFlag::SELF );
1291 if ( !xDispatch.is() )
1292 return;
1294 sal_Int8 nType = 0;
1295 OUString aFilterName;
1296 css::uno::Reference< css::lang::XComponent > xDrawing;
1297 css::uno::Reference< css::graphic::XGraphic > xGraphic;
1299 aFilterName = GetFilterName();
1301 switch( mpCurTheme->GetObjectKind( mnCurActionPos ) )
1303 case SgaObjKind::Bitmap:
1304 case SgaObjKind::Animation:
1305 case SgaObjKind::Inet:
1306 // TODO drawing objects are inserted as drawings only via drag&drop
1307 case SgaObjKind::SvDraw:
1308 nType = css::gallery::GalleryItemType::GRAPHIC;
1309 break;
1311 case SgaObjKind::Sound :
1312 nType = css::gallery::GalleryItemType::MEDIA;
1313 break;
1315 default:
1316 nType = css::gallery::GalleryItemType::EMPTY;
1317 break;
1320 Graphic aGraphic;
1321 bool bGraphic = mpCurTheme->GetGraphic( mnCurActionPos, aGraphic );
1322 if ( bGraphic && !aGraphic.IsNone() )
1323 xGraphic.set( aGraphic.GetXGraphic() );
1324 OSL_ENSURE( xGraphic.is(), "gallery item is graphic, but the reference is invalid!" );
1326 css::uno::Sequence< css::beans::PropertyValue > aSeq{
1327 comphelper::makePropertyValue(SVXGALLERYITEM_TYPE, nType),
1328 comphelper::makePropertyValue(SVXGALLERYITEM_URL, OUString()),
1329 comphelper::makePropertyValue(SVXGALLERYITEM_FILTER, aFilterName),
1330 comphelper::makePropertyValue(SVXGALLERYITEM_DRAWING, xDrawing),
1331 comphelper::makePropertyValue(SVXGALLERYITEM_GRAPHIC, xGraphic)
1333 assert(aSeq.getLength() == SVXGALLERYITEM_PARAMS);
1335 css::uno::Sequence< css::beans::PropertyValue > aArgs{ comphelper::makePropertyValue(
1336 SVXGALLERYITEM_ARGNAME, aSeq) };
1338 std::unique_ptr<DispatchInfo> pInfo(new DispatchInfo);
1339 pInfo->TargetURL = std::move(aURL);
1340 pInfo->Arguments = std::move(aArgs);
1341 pInfo->Dispatch = std::move(xDispatch);
1343 if ( Application::PostUserEvent(
1344 LINK( nullptr, GalleryBrowser1, AsyncDispatch_Impl), pInfo.get() ) )
1345 pInfo.release();
1348 void GalleryBrowser1::Execute(std::u16string_view rIdent)
1350 Point aSelPos;
1351 const sal_uInt32 nItemId = ImplGetSelectedItemId( nullptr, aSelPos );
1353 if( !(mpCurTheme && nItemId) )
1354 return;
1356 mnCurActionPos = nItemId - 1;
1358 if (rIdent == u"preview")
1359 SetMode( ( GALLERYBROWSERMODE_PREVIEW != GetMode() ) ? GALLERYBROWSERMODE_PREVIEW : meLastMode );
1360 else if (rIdent == u"delete")
1362 if (!mpCurTheme->IsReadOnly())
1364 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetViewWindow(), u"svx/ui/querydeleteobjectdialog.ui"_ustr));
1365 std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog(u"QueryDeleteObjectDialog"_ustr));
1366 if (xQuery->run() == RET_YES)
1368 mpCurTheme->RemoveObject( mnCurActionPos );
1372 else if (rIdent == u"title")
1374 std::unique_ptr<SgaObject> pObj = mpCurTheme->AcquireObject( mnCurActionPos );
1376 if( pObj )
1378 const OUString aOldTitle( GetItemText( *pObj, GalleryItemFlags::Title ) );
1380 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1381 ScopedVclPtr<AbstractTitleDialog> aDlg(pFact->CreateTitleDialog(GetViewWindow(), aOldTitle));
1382 if( aDlg->Execute() == RET_OK )
1384 OUString aNewTitle( aDlg->GetTitle() );
1386 if( ( aNewTitle.isEmpty() && !pObj->GetTitle().isEmpty() ) || ( aNewTitle != aOldTitle ) )
1388 if( aNewTitle.isEmpty() )
1389 aNewTitle = "__<empty>__";
1391 pObj->SetTitle( aNewTitle );
1392 mpCurTheme->InsertObject( *pObj );
1397 else if (rIdent == u"copy")
1399 mpCurTheme->CopyToClipboard(*GetViewWindow(), mnCurActionPos);
1401 else if (rIdent == u"paste")
1403 if( !mpCurTheme->IsReadOnly() )
1405 weld::Widget* pParent = GetViewWindow();
1406 TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromClipboard(pParent->get_clipboard()));
1407 mpCurTheme->InsertTransferable( aDataHelper.GetTransferable(), mnCurActionPos );
1412 OUString GalleryBrowser1::GetItemText( const SgaObject& rObj, GalleryItemFlags nItemTextFlags )
1414 OUString aRet;
1416 const INetURLObject& aURL(rObj.GetURL());
1418 if( nItemTextFlags & GalleryItemFlags::Title )
1420 OUString aTitle( rObj.GetTitle() );
1422 if( aTitle.isEmpty() )
1423 aTitle = aURL.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::Unambiguous );
1425 if( aTitle.isEmpty() )
1427 aTitle = aURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous );
1428 aTitle = aTitle.copy( aTitle.lastIndexOf('/')+1 );
1431 aRet += aTitle;
1434 if( nItemTextFlags & GalleryItemFlags::Path )
1436 const OUString aPath( aURL.getFSysPath( FSysStyle::Detect ) );
1438 if( !aPath.isEmpty() && ( nItemTextFlags & GalleryItemFlags::Title ) )
1439 aRet += " (";
1441 aRet += aURL.getFSysPath( FSysStyle::Detect );
1443 if( !aPath.isEmpty() && ( nItemTextFlags & GalleryItemFlags::Title ) )
1444 aRet += ")";
1447 return aRet;
1450 INetURLObject GalleryBrowser1::GetURL() const
1452 INetURLObject aURL;
1454 if( mpCurTheme && mnCurActionPos != 0xffffffff )
1455 aURL = mpCurTheme->GetObjectURL( mnCurActionPos );
1457 return aURL;
1460 OUString GalleryBrowser1::GetFilterName() const
1462 OUString aFilterName;
1464 if( mpCurTheme && mnCurActionPos != 0xffffffff )
1466 const SgaObjKind eObjKind = mpCurTheme->GetObjectKind( mnCurActionPos );
1468 if( ( SgaObjKind::Bitmap == eObjKind ) || ( SgaObjKind::Animation == eObjKind ) )
1470 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
1471 INetURLObject aURL;
1472 mpCurTheme->GetURL( mnCurActionPos, aURL );
1473 sal_uInt16 nFilter = rFilter.GetImportFormatNumberForShortName(aURL.GetFileExtension());
1475 if( GRFILTER_FORMAT_DONTKNOW != nFilter )
1476 aFilterName = rFilter.GetImportFormatName( nFilter );
1480 return aFilterName;
1483 IMPL_LINK_NOARG(GalleryBrowser1, SelectObjectValueSetHdl, ValueSet*, void)
1485 ImplUpdateSelection();
1488 IMPL_LINK_NOARG(GalleryBrowser1, SelectObjectHdl, weld::TreeView&, void)
1490 ImplUpdateSelection();
1493 IMPL_LINK(GalleryBrowser1, SelectTbxHdl, weld::Toggleable&, rBox, void)
1495 if (&rBox == mxIconButton.get())
1496 SetMode(rBox.get_active() ? GALLERYBROWSERMODE_ICON : GALLERYBROWSERMODE_LIST);
1497 else if (&rBox == mxListButton.get())
1498 SetMode(rBox.get_active() ? GALLERYBROWSERMODE_LIST : GALLERYBROWSERMODE_ICON);
1501 void GalleryBrowser1::FillThemeEntries()
1503 for (size_t i = 0, nCount = mpGallery->GetThemeCount(); i < nCount; ++i)
1505 const GalleryThemeEntry* pThemeInfo = mpGallery->GetThemeInfo( i );
1506 OUString aThemeName = pThemeInfo->GetThemeName();
1507 //sal_uInt32 nId = pThemeInfo->GetId();
1508 if (GalleryTheme* pTheme = mpGallery->AcquireTheme(aThemeName, maLocalListener))
1510 sal_uInt32 nObjectCount = pTheme->GetObjectCount();
1511 for (size_t nObject = 0; nObject < nObjectCount; ++nObject)
1513 if (std::unique_ptr<SgaObject> xSgaObject = pTheme->AcquireObject(nObject))
1515 OUString aTitle = GetItemText(*xSgaObject, GalleryItemFlags::Title);
1516 maAllThemeEntries.push_back(ThemeEntry(aThemeName, aTitle, nObject));
1519 mpGallery->ReleaseTheme(pTheme, maLocalListener);
1522 maFoundThemeEntries.assign(maAllThemeEntries.begin(), maAllThemeEntries.end());
1524 IMPL_LINK(GalleryBrowser1, SearchHdl, weld::Entry&, searchEdit, void)
1526 OUString search = searchEdit.get_text().trim();
1527 OUString curThemeName;
1528 ::std::set<OUString> aFoundThemes;
1529 if (mpCurTheme)
1531 curThemeName = mpCurTheme->GetName();
1533 if (search.isEmpty())
1535 maFoundThemeEntries.assign(maAllThemeEntries.begin(), maAllThemeEntries.end());
1536 if (maAllThemeEntries.begin() != maAllThemeEntries.end())
1537 curThemeName = maAllThemeEntries.begin()->maThemeName;
1539 else
1541 search = "*" + search + "*";
1542 WildCard aSearchExpression(m_aCharacterClassficator.lowercase(search));
1543 bool currentThemeFound = false;
1544 maFoundThemeEntries.clear();
1545 for (GalleryThemeEntries::const_iterator allIter = maAllThemeEntries.begin(); allIter != maAllThemeEntries.end(); ++allIter)
1547 if (aSearchExpression.Matches(m_aCharacterClassficator.lowercase(allIter->maEntryTitle)))
1549 maFoundThemeEntries.push_back(*allIter);
1550 aFoundThemes.insert(allIter->maThemeName);
1551 if (curThemeName == allIter->maThemeName)
1552 currentThemeFound = true;
1555 if (!currentThemeFound)
1557 if (maFoundThemeEntries.begin() != maFoundThemeEntries.end())
1558 curThemeName = maFoundThemeEntries.begin()->maThemeName;
1559 else
1560 curThemeName.clear();
1563 mxThemes->clear();
1564 if (search.isEmpty())
1566 for (size_t i = 0, nCount = mpGallery->GetThemeCount(); i < nCount; ++i)
1567 ImplInsertThemeEntry( mpGallery->GetThemeInfo( i ) );
1569 else
1571 for(std::set<OUString>::iterator foundIter = aFoundThemes.begin(); foundIter != aFoundThemes.end(); ++foundIter)
1572 ImplInsertThemeEntry(mpGallery->GetThemeInfo(*foundIter));
1574 mxThemes->select_text(curThemeName);
1575 SelectTheme(curThemeName);
1578 namespace
1581 GalleryThemePopup::GalleryThemePopup(
1582 weld::Widget* pParent,
1583 const GalleryTheme* pTheme,
1584 sal_uInt32 nObjectPos,
1585 bool bPreview,
1586 GalleryBrowser1* pBrowser )
1587 : mpTheme( pTheme )
1588 , mnObjectPos( nObjectPos )
1589 , mbPreview( bPreview )
1590 , mxBuilder(Application::CreateBuilder(pParent, u"svx/ui/gallerymenu2.ui"_ustr))
1591 , mxPopupMenu(mxBuilder->weld_menu(u"menu"_ustr))
1592 , mxBackgroundPopup(mxBuilder->weld_menu(u"backgroundmenu"_ustr))
1593 , mpBrowser( pBrowser )
1595 // SID_GALLERY_ENABLE_ADDCOPY
1596 m_aCommandInfo.emplace(
1597 SID_GALLERY_ENABLE_ADDCOPY,
1598 CommandInfo( u".uno:GalleryEnableAddCopy"_ustr ));
1599 // SID_GALLERY_BG_BRUSH
1600 m_aCommandInfo.emplace(
1601 SID_GALLERY_BG_BRUSH,
1602 CommandInfo( u".uno:BackgroundImage"_ustr ));
1603 // SID_GALLERY_FORMATS
1604 m_aCommandInfo.emplace(
1605 SID_GALLERY_FORMATS,
1606 CommandInfo( u".uno:InsertGalleryPic"_ustr ));
1610 void SAL_CALL GalleryThemePopup::statusChanged(
1611 const css::frame::FeatureStateEvent &rEvent )
1613 const OUString &rURL = rEvent.FeatureURL.Complete;
1614 if ( rURL == ".uno:GalleryEnableAddCopy" )
1616 if ( !rEvent.IsEnabled )
1618 mxPopupMenu->set_visible(u"add"_ustr, false);
1621 else if ( rURL == ".uno:BackgroundImage" )
1623 mxBackgroundPopup->clear();
1624 if ( rEvent.IsEnabled )
1626 OUString sItem;
1627 css::uno::Sequence< OUString > sItems;
1628 if ( ( rEvent.State >>= sItem ) && sItem.getLength() )
1630 mxBackgroundPopup->append(OUString::number(1), sItem);
1632 else if ( ( rEvent.State >>= sItems ) && sItems.hasElements() )
1634 sal_uInt16 nId = 1;
1635 for (const OUString& rStr : sItems)
1637 mxBackgroundPopup->append(OUString::number(nId), rStr);
1638 nId++;
1645 void SAL_CALL GalleryThemePopup::disposing(
1646 const css::lang::EventObject &/*rSource*/)
1650 void GalleryThemePopup::Execute(
1651 const CommandInfo &rCmdInfo,
1652 const css::uno::Sequence< css::beans::PropertyValue > &rArguments )
1654 if ( rCmdInfo.Dispatch.is() )
1656 std::unique_ptr<DispatchInfo> pInfo(new DispatchInfo);
1657 pInfo->TargetURL = rCmdInfo.URL;
1658 pInfo->Arguments = rArguments;
1659 pInfo->Dispatch = rCmdInfo.Dispatch;
1661 if ( Application::PostUserEvent(
1662 LINK( nullptr, GalleryBrowser1, AsyncDispatch_Impl), pInfo.get() ) )
1663 pInfo.release();
1667 void GalleryThemePopup::ExecutePopup(weld::Widget* pParent, const ::Point &rPos)
1669 css::uno::Reference< css::frame::XStatusListener > xThis( this );
1671 const SgaObjKind eObjKind = mpTheme->GetObjectKind( mnObjectPos );
1672 INetURLObject aURL;
1674 mpTheme->GetURL(mnObjectPos, aURL);
1675 const bool bValidURL = ( aURL.GetProtocol() != INetProtocol::NotValid );
1677 mxPopupMenu->set_visible(u"add"_ustr, bValidURL && SgaObjKind::Sound != eObjKind);
1679 mxPopupMenu->set_visible(u"preview"_ustr, bValidURL);
1680 mxPopupMenu->set_active(u"preview"_ustr, mbPreview);
1682 if( mpTheme->IsReadOnly() || !mpTheme->GetObjectCount() )
1684 mxPopupMenu->set_visible(u"delete"_ustr, false);
1685 mxPopupMenu->set_visible(u"title"_ustr, false);
1686 if (mpTheme->IsReadOnly())
1687 mxPopupMenu->set_visible(u"paste"_ustr, false);
1689 if (!mpTheme->GetObjectCount())
1690 mxPopupMenu->set_visible(u"copy"_ustr, false);
1692 else
1694 mxPopupMenu->set_visible(u"delete"_ustr, !mbPreview);
1695 mxPopupMenu->set_visible(u"title"_ustr, true);
1696 mxPopupMenu->set_visible(u"copy"_ustr, true);
1697 mxPopupMenu->set_visible(u"paste"_ustr, true);
1700 // update status
1701 css::uno::Reference< css::frame::XDispatchProvider> xDispatchProvider(
1702 GalleryBrowser1::GetFrame(), css::uno::UNO_QUERY );
1703 css::uno::Reference< css::util::XURLTransformer > xTransformer(
1704 mpBrowser->GetURLTransformer() );
1705 for ( auto& rInfo : m_aCommandInfo )
1709 CommandInfo &rCmdInfo = rInfo.second;
1710 if ( xTransformer.is() )
1711 xTransformer->parseStrict( rCmdInfo.URL );
1713 if ( xDispatchProvider.is() )
1715 rCmdInfo.Dispatch = xDispatchProvider->queryDispatch(
1716 rCmdInfo.URL,
1717 u"_self"_ustr,
1718 css::frame::FrameSearchFlag::SELF );
1721 if ( rCmdInfo.Dispatch.is() )
1723 rCmdInfo.Dispatch->addStatusListener( this, rCmdInfo.URL );
1724 rCmdInfo.Dispatch->removeStatusListener( this, rCmdInfo.URL );
1727 catch ( ... )
1731 if( !mxBackgroundPopup->n_children() || ( eObjKind == SgaObjKind::SvDraw ) || ( eObjKind == SgaObjKind::Sound ) )
1732 mxPopupMenu->set_visible(u"background"_ustr, false);
1733 else
1734 mxPopupMenu->set_visible(u"background"_ustr, true);
1736 MenuSelectHdl(mxPopupMenu->popup_at_rect(pParent, tools::Rectangle(rPos, Size(1,1))));
1739 void GalleryThemePopup::MenuSelectHdl(std::u16string_view rIdent)
1741 if (rIdent.empty())
1742 return;
1744 sal_uInt16 nSubMenuId = o3tl::toUInt32(rIdent);
1745 if (nSubMenuId)
1747 BackgroundMenuSelectHdl(nSubMenuId-1);
1748 return;
1751 if (rIdent == u"add")
1753 const CommandInfoMap::const_iterator it = m_aCommandInfo.find( SID_GALLERY_FORMATS );
1754 if (it != m_aCommandInfo.end())
1755 mpBrowser->DispatchAdd(it->second.Dispatch, it->second.URL);
1757 else
1758 mpBrowser->Execute(rIdent);
1761 void GalleryThemePopup::BackgroundMenuSelectHdl(sal_uInt16 nPos)
1763 OUString aURL( mpBrowser->GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1764 OUString aFilterName( mpBrowser->GetFilterName() );
1766 css::uno::Sequence< css::beans::PropertyValue > aArgs{
1767 comphelper::makePropertyValue(u"Background.Transparent"_ustr, sal_Int32( 0 )), // 0 - 100
1768 comphelper::makePropertyValue(u"Background.BackColor"_ustr, sal_Int32( - 1 )),
1769 comphelper::makePropertyValue(u"Background.URL"_ustr, aURL),
1770 comphelper::makePropertyValue(u"Background.Filtername"_ustr, aFilterName), // FIXME name should be FilterName
1771 comphelper::makePropertyValue(u"Background.Position"_ustr, css::style::GraphicLocation_TILED),
1772 comphelper::makePropertyValue(u"Position"_ustr, nPos)
1775 const CommandInfoMap::const_iterator it = m_aCommandInfo.find( SID_GALLERY_BG_BRUSH );
1776 if ( it != m_aCommandInfo.end() )
1777 Execute( it->second, aArgs );
1780 } // end anonymous namespace
1783 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */