LibreOffice Module svx (master)  1
galbrws1.cxx
Go to the documentation of this file.
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 <sal/config.h>
21 
23 #include <tools/datetime.hxx>
24 #include <unotools/datetime.hxx>
25 #include <vcl/commandevent.hxx>
26 #include <vcl/event.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/weld.hxx>
29 #include <ucbhelper/content.hxx>
30 #include <com/sun/star/ucb/ContentCreationException.hpp>
31 #include <sfx2/app.hxx>
32 #include <helpids.h>
33 #include <svx/gallery1.hxx>
34 #include <svx/galtheme.hxx>
35 #include <svx/galmisc.hxx>
36 #include "galbrws1.hxx"
37 #include <com/sun/star/util/DateTime.hpp>
38 #include <svx/strings.hrc>
39 #include <algorithm>
40 #include <svx/dialmgr.hxx>
42 #include <com/sun/star/beans/PropertyValue.hpp>
43 #include <svx/svxdlg.hxx>
44 #include <memory>
45 #include <bitmaps.hlst>
46 
47 using namespace ::com::sun::star;
48 
50  weld::Builder& rBuilder,
51  Gallery* pGallery,
52  const std::function<void ()>& rThemeSelectionHandler)
53  :
54  mxNewTheme(rBuilder.weld_button("insert")),
55  mxThemes(rBuilder.weld_tree_view("themelist")),
56  mxMoreGalleries(rBuilder.weld_button("btnMoreGalleries")),
57  mpGallery ( pGallery ),
58  mpExchangeData ( new ExchangeData ),
59  aImgNormal ( RID_SVXBMP_THEME_NORMAL ),
60  aImgDefault ( RID_SVXBMP_THEME_DEFAULT ),
61  aImgReadOnly ( RID_SVXBMP_THEME_READONLY ),
62  maThemeSelectionHandler(rThemeSelectionHandler)
63 {
64  mxNewTheme->set_help_id(HID_GALLERY_NEWTHEME);
65  mxNewTheme->connect_clicked( LINK( this, GalleryBrowser1, ClickNewThemeHdl ) );
66 
67  mxThemes->make_sorted();
68  mxThemes->set_help_id( HID_GALLERY_THEMELIST );
69  mxThemes->connect_changed( LINK( this, GalleryBrowser1, SelectThemeHdl ) );
70  mxThemes->connect_popup_menu(LINK(this, GalleryBrowser1, PopupMenuHdl));
71  mxThemes->connect_key_press(LINK(this, GalleryBrowser1, KeyInputHdl));
72  mxThemes->set_size_request(-1, mxThemes->get_height_rows(6));
73 
74  mxMoreGalleries->set_from_icon_name("cmd/sc_additionsdialog.png");
75  mxMoreGalleries->connect_clicked(LINK(this, GalleryBrowser1, OnMoreGalleriesClick));
76 
77  // disable creation of new themes if a writable directory is not available
78  if( mpGallery->GetUserURL().GetProtocol() == INetProtocol::NotValid )
79  mxNewTheme->set_sensitive(false);
80 
82 
83  for (size_t i = 0, nCount = mpGallery->GetThemeCount(); i < nCount; ++i)
85 }
86 
88 {
90  mpExchangeData.reset();
91 }
92 
94 {
95  static const bool bShowHiddenThemes = ( getenv( "GALLERY_SHOW_HIDDEN_THEMES" ) != nullptr );
96 
97  if( !(pEntry && ( !pEntry->IsHidden() || bShowHiddenThemes )) )
98  return;
99 
100  const OUString* pImage;
101 
102  if( pEntry->IsReadOnly() )
103  pImage = &aImgReadOnly;
104  else if( pEntry->IsDefault() )
105  pImage = &aImgDefault;
106  else
107  pImage = &aImgNormal;
108 
109  mxThemes->append("", pEntry->GetThemeName(), *pImage);
110 }
111 
113 {
114  rData.pTheme = const_cast<GalleryTheme*>(pThm);
115  rData.aEditedTitle = pThm->GetName();
116 
117  try
118  {
119  DateTime aDateTime(pThm->getModificationDate());
120 
121  rData.aThemeChangeDate = aDateTime;
122  rData.aThemeChangeTime = aDateTime;
123  }
124  catch( const ucb::ContentCreationException& )
125  {
126  }
127  catch( const uno::RuntimeException& )
128  {
129  }
130  catch( const uno::Exception& )
131  {
132  }
133 }
134 
135 void GalleryBrowser1::ImplGetExecuteVector(std::vector<OString>& o_aExec)
136 {
137  GalleryTheme* pTheme = mpGallery->AcquireTheme( GetSelectedTheme(), *this );
138 
139  if( !pTheme )
140  return;
141 
142  bool bUpdateAllowed, bRenameAllowed, bRemoveAllowed;
143  static const bool bIdDialog = ( getenv( "GALLERY_ENABLE_ID_DIALOG" ) != nullptr );
144 
145  if( pTheme->IsReadOnly() )
146  bUpdateAllowed = bRenameAllowed = bRemoveAllowed = false;
147  else if( pTheme->IsDefault() )
148  {
149  bUpdateAllowed = bRenameAllowed = true;
150  bRemoveAllowed = false;
151  }
152  else
153  bUpdateAllowed = bRenameAllowed = bRemoveAllowed = true;
154 
155  if( bUpdateAllowed && pTheme->GetObjectCount() )
156  o_aExec.emplace_back("update");
157 
158  if( bRenameAllowed )
159  o_aExec.emplace_back("rename");
160 
161  if( bRemoveAllowed )
162  o_aExec.emplace_back("delete");
163 
164  if( bIdDialog && !pTheme->IsReadOnly() )
165  o_aExec.emplace_back("assign");
166 
167  o_aExec.emplace_back("properties");
168 
169  mpGallery->ReleaseTheme( pTheme, *this );
170 }
171 
172 void GalleryBrowser1::ImplGalleryThemeProperties( const OUString & rThemeName, bool bCreateNew )
173 {
174  DBG_ASSERT(!mpThemePropsDlgItemSet, "mpThemePropsDlgItemSet already set!");
175  mpThemePropsDlgItemSet.reset(new SfxItemSet( SfxGetpApp()->GetPool() ));
176  GalleryTheme* pTheme = mpGallery->AcquireTheme( rThemeName, *this );
177 
179 
182 
183  if ( bCreateNew )
184  {
185  xThemePropertiesDialog->StartExecuteAsync([xThemePropertiesDialog, this](sal_Int32 nResult){
187  xThemePropertiesDialog->disposeOnce();
188  });
189  }
190  else
191  {
192  xThemePropertiesDialog->StartExecuteAsync([xThemePropertiesDialog, this](sal_Int32 nResult){
193  EndThemePropertiesDlgHdl(nResult);
194  xThemePropertiesDialog->disposeOnce();
195  });
196  }
197 }
198 
199 void GalleryBrowser1::ImplEndGalleryThemeProperties(bool bCreateNew, sal_Int32 nRet)
200 {
201  if( nRet == RET_OK )
202  {
203  OUString aName( mpExchangeData->pTheme->GetName() );
204 
205  if( !mpExchangeData->aEditedTitle.isEmpty() && aName != mpExchangeData->aEditedTitle )
206  {
207  OUString aTitle( mpExchangeData->aEditedTitle );
208  sal_uInt16 nCount = 0;
209 
210  while( mpGallery->HasTheme( aTitle ) && ( nCount++ < 16000 ) )
211  {
212  aTitle = mpExchangeData->aEditedTitle + " " + OUString::number( nCount );
213  }
214 
215  mpGallery->RenameTheme( aName, aTitle );
216  }
217 
218  if ( bCreateNew )
219  {
220  mxThemes->select_text( mpExchangeData->pTheme->GetName() );
221  SelectThemeHdl( *mxThemes );
222  }
223  }
224 
225  OUString aThemeName( mpExchangeData->pTheme->GetName() );
226  mpGallery->ReleaseTheme( mpExchangeData->pTheme, *this );
227 
228  if ( bCreateNew && ( nRet != RET_OK ) )
229  {
230  mpGallery->RemoveTheme( aThemeName );
231  }
232 }
233 
235 {
236  ImplEndGalleryThemeProperties(true, nResult);
237 }
238 
240 {
241  ImplEndGalleryThemeProperties(false, nResult);
242 }
243 
244 void GalleryBrowser1::ImplExecute(const OString &rIdent)
245 {
246  if (rIdent == "update")
247  {
248  GalleryTheme* pTheme = mpGallery->AcquireTheme( GetSelectedTheme(), *this );
249 
251  ScopedVclPtr<VclAbstractDialog> aActualizeProgress(pFact->CreateActualizeProgressDialog(mxThemes.get(), pTheme));
252 
253  aActualizeProgress->Execute();
254  mpGallery->ReleaseTheme( pTheme, *this );
255  }
256  else if (rIdent == "delete")
257  {
258  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(mxThemes.get(), "svx/ui/querydeletethemedialog.ui"));
259  std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("QueryDeleteThemeDialog"));
260  if (xQuery->run() == RET_YES)
261  mpGallery->RemoveTheme( mxThemes->get_selected_text() );
262  }
263  else if (rIdent == "rename")
264  {
265  GalleryTheme* pTheme = mpGallery->AcquireTheme( GetSelectedTheme(), *this );
266  const OUString aOldName( pTheme->GetName() );
267 
269  ScopedVclPtr<AbstractTitleDialog> aDlg(pFact->CreateTitleDialog(mxThemes.get(), aOldName));
270 
271  if( aDlg->Execute() == RET_OK )
272  {
273  const OUString aNewName( aDlg->GetTitle() );
274 
275  if( !aNewName.isEmpty() && ( aNewName != aOldName ) )
276  {
277  OUString aName( aNewName );
278  sal_uInt16 nCount = 0;
279 
280  while( mpGallery->HasTheme( aName ) && ( nCount++ < 16000 ) )
281  {
282  aName = aNewName + " " + OUString::number( nCount );
283  }
284 
285  mpGallery->RenameTheme( aOldName, aName );
286  }
287  }
288  mpGallery->ReleaseTheme( pTheme, *this );
289  }
290  else if (rIdent == "assign")
291  {
292  GalleryTheme* pTheme = mpGallery->AcquireTheme( GetSelectedTheme(), *this );
293 
294  if (pTheme && !pTheme->IsReadOnly())
295  {
296 
299  if( aDlg->Execute() == RET_OK )
300  pTheme->SetId( aDlg->GetId(), true );
301  }
302 
303  mpGallery->ReleaseTheme( pTheme, *this );
304  }
305  else if (rIdent == "properties")
306  {
308  }
309 }
310 
312 {
313  if (mxNewTheme->get_sensitive())
314  mxNewTheme->grab_focus();
315  else
316  mxThemes->grab_focus();
317 }
318 
320 {
321  const GalleryHint& rGalleryHint = static_cast<const GalleryHint&>(rHint);
322 
323  switch( rGalleryHint.GetType() )
324  {
327  break;
328 
330  {
331  const sal_Int32 nCurSelectPos = mxThemes->get_selected_index();
332  const sal_Int32 nRenameEntryPos = mxThemes->find_text( rGalleryHint.GetThemeName() );
333 
334  mxThemes->remove_text( rGalleryHint.GetThemeName() );
336 
337  if( nCurSelectPos == nRenameEntryPos )
338  {
339  mxThemes->select_text( rGalleryHint.GetStringData() );
340  SelectThemeHdl( *mxThemes );
341  }
342  }
343  break;
344 
346  {
347  mxThemes->remove_text( rGalleryHint.GetThemeName() );
348  }
349  break;
350 
352  {
353  const sal_Int32 nCurSelectPos = mxThemes->get_selected_index();
354  const sal_Int32 nCloseEntryPos = mxThemes->find_text( rGalleryHint.GetThemeName() );
355 
356  if( nCurSelectPos == nCloseEntryPos )
357  {
358  if( nCurSelectPos < ( mxThemes->n_children() - 1 ) )
359  mxThemes->select( nCurSelectPos + 1 );
360  else if( nCurSelectPos )
361  mxThemes->select( nCurSelectPos - 1 );
362  else
363  mxThemes->select(-1);
364 
365  SelectThemeHdl( *mxThemes );
366  }
367  }
368  break;
369 
370  default:
371  break;
372  }
373 }
374 
375 IMPL_STATIC_LINK_NOARG( GalleryBrowser1, OnMoreGalleriesClick, weld::Button&, void)
376 {
377  css::uno::Sequence<css::beans::PropertyValue> aArgs(1);
378  aArgs[0].Name = "AdditionsTag";
379  aArgs[0].Value <<= OUString("Gallery");
380  comphelper::dispatchCommand(".uno:AdditionsDialog", aArgs);
381 }
382 
383 IMPL_LINK(GalleryBrowser1, KeyInputHdl, const KeyEvent&, rKEvt, bool)
384 {
385  bool bRet = false;
386 
387  std::vector<OString> aExecVector;
388  ImplGetExecuteVector(aExecVector);
389  OString sExecuteIdent;
390  bool bMod1 = rKEvt.GetKeyCode().IsMod1();
391 
392  switch( rKEvt.GetKeyCode().GetCode() )
393  {
394  case KEY_INSERT:
395  ClickNewThemeHdl(*mxNewTheme);
396  break;
397 
398  case KEY_I:
399  {
400  if( bMod1 )
401  ClickNewThemeHdl(*mxNewTheme);
402  }
403  break;
404 
405  case KEY_U:
406  {
407  if( bMod1 )
408  sExecuteIdent = "update";
409  }
410  break;
411 
412  case KEY_DELETE:
413  sExecuteIdent = "delete";
414  break;
415 
416  case KEY_D:
417  {
418  if( bMod1 )
419  sExecuteIdent = "delete";
420  }
421  break;
422 
423  case KEY_R:
424  {
425  if( bMod1 )
426  sExecuteIdent = "rename";
427  }
428  break;
429 
430  case KEY_RETURN:
431  {
432  if( bMod1 )
433  sExecuteIdent = "properties";
434  }
435  break;
436  }
437 
438  if (!sExecuteIdent.isEmpty() && (std::find( aExecVector.begin(), aExecVector.end(), sExecuteIdent) != aExecVector.end()))
439  {
440  ImplExecute(sExecuteIdent);
441  bRet = true;
442  }
443 
444  return bRet;
445 }
446 
447 IMPL_LINK(GalleryBrowser1, PopupMenuHdl, const CommandEvent&, rCEvt, bool)
448 {
449  if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
450  return false;
451 
452  std::vector<OString> aExecVector;
453  ImplGetExecuteVector(aExecVector);
454 
455  if (aExecVector.empty())
456  return true;
457 
458  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(mxThemes.get(), "svx/ui/gallerymenu1.ui"));
459  std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("menu"));
460 
461  xMenu->set_visible("update", std::find( aExecVector.begin(), aExecVector.end(), "update" ) != aExecVector.end());
462  xMenu->set_visible("rename", std::find( aExecVector.begin(), aExecVector.end(), "rename" ) != aExecVector.end());
463  xMenu->set_visible("delete", std::find( aExecVector.begin(), aExecVector.end(), "delete" ) != aExecVector.end());
464  xMenu->set_visible("assign", std::find( aExecVector.begin(), aExecVector.end(), "assign" ) != aExecVector.end());
465  xMenu->set_visible("properties", std::find( aExecVector.begin(), aExecVector.end(), "properties" ) != aExecVector.end());
466 
467  OString sCommand(xMenu->popup_at_rect(mxThemes.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1))));
468  ImplExecute(sCommand);
469 
470  return true;
471 }
472 
474 {
475  if (maThemeSelectionHandler)
476  maThemeSelectionHandler();
477 }
478 
479 IMPL_LINK_NOARG(GalleryBrowser1, ClickNewThemeHdl, weld::Button&, void)
480 {
481  OUString aNewTheme( SvxResId(RID_SVXSTR_GALLERY_NEWTHEME) );
482  OUString aName( aNewTheme );
483  sal_uInt16 nCount = 0;
484 
485  while( mpGallery->HasTheme( aName ) && ( nCount++ < 16000 ) )
486  {
487  aName = aNewTheme + " " + OUString::number( nCount );
488  }
489 
490  if( !mpGallery->HasTheme( aName ) && mpGallery->CreateTheme( aName ) )
491  {
492  ImplGalleryThemeProperties( aName, true );
493  }
494 }
495 
496 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: galbrws1.cxx:319
bool IsDefault() const
Definition: galtheme.cxx:788
virtual VclPtr< VclAbstractDialog > CreateActualizeProgressDialog(weld::Widget *pParent, GalleryTheme *pThm)=0
#define HID_GALLERY_NEWTHEME
Definition: helpids.h:30
GalleryTheme * AcquireTheme(const OUString &rThemeName, SfxListener &rListener)
Definition: gallery1.cxx:694
void GrabFocus()
Definition: galbrws1.cxx:311
static SvxAbstractDialogFactory * Create()
Definition: svxdlg.cxx:22
void ImplEndGalleryThemeProperties(bool bCreateNew, sal_Int32 nResult)
Definition: galbrws1.cxx:199
static weld::Builder * CreateBuilder(weld::Widget *pParent, const OUString &rUIFile, bool bMobile=false)
virtual OUString GetTitle() const =0
#define HID_GALLERY_THEMELIST
Definition: helpids.h:31
void ImplGetExecuteVector(std::vector< OString > &o_aExec)
Definition: galbrws1.cxx:135
bool IsReadOnly() const
Definition: gallery1.hxx:66
virtual short Execute()=0
OUString aImgDefault
Definition: galbrws1.hxx:54
IMPL_LINK(GalleryBrowser1, KeyInputHdl, const KeyEvent &, rKEvt, bool)
Definition: galbrws1.cxx:383
SfxApplication * SfxGetpApp()
size_t GetThemeCount() const
Definition: gallery1.hxx:123
RET_YES
OUString aImgReadOnly
Definition: galbrws1.hxx:55
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:25
std::unique_ptr< ExchangeData > mpExchangeData
Definition: galbrws1.hxx:50
std::unique_ptr< weld::Button > mxMoreGalleries
Definition: galbrws1.hxx:48
void RenameTheme(const OUString &rOldName, const OUString &rNewName)
Definition: gallery1.cxx:596
bool dispatchCommand(const OUString &rCommand, const uno::Reference< css::frame::XFrame > &rFrame, const css::uno::Sequence< css::beans::PropertyValue > &rArguments, const uno::Reference< css::frame::XDispatchResultListener > &rListener)
constexpr sal_uInt16 KEY_D
int nCount
const OUString & GetThemeName() const
Definition: galmisc.hxx:192
bool RemoveTheme(const OUString &rThemeName)
Definition: gallery1.cxx:619
bool IsHidden() const
Definition: gallery1.hxx:69
constexpr sal_uInt16 KEY_R
Gallery * mpGallery
Definition: galbrws1.hxx:49
GalleryHintType GetType() const
Definition: galmisc.hxx:191
void EndNewThemePropertiesDlgHdl(sal_Int32 nResult)
Definition: galbrws1.cxx:234
SAL_DLLPRIVATE const INetURLObject & GetUserURL() const
Definition: gallery1.hxx:140
#define DBG_ASSERT(sCon, aError)
int i
virtual VclPtr< AbstractGalleryIdDialog > CreateGalleryIdDialog(weld::Widget *pParent, GalleryTheme *pThm)=0
GalleryTheme * pTheme
Definition: galmisc.hxx:42
OUString GetSelectedTheme() const
Definition: galbrws1.hxx:87
void ImplGalleryThemeProperties(const OUString &rThemeName, bool bCreateNew)
Definition: galbrws1.cxx:172
SAL_DLLPRIVATE sal_uInt32 GetObjectCount() const
Definition: galtheme.hxx:84
GalleryBrowser1(weld::Builder &rBuilder, Gallery *pGallery, const ::std::function< void()> &rThemeSelectionHandler)
Definition: galbrws1.cxx:49
std::unique_ptr< SfxItemSet > mpThemePropsDlgItemSet
Definition: galbrws1.hxx:51
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
bool StartExecuteAsync(const std::function< void(sal_Int32)> &rEndDialogFn)
constexpr sal_uInt16 KEY_RETURN
tools::Time aThemeChangeTime
Definition: galmisc.hxx:45
bool IsDefault() const
Definition: gallery1.cxx:719
bool HasTheme(const OUString &rThemeName)
Definition: gallery1.cxx:570
DateTime getModificationDate() const
Definition: galtheme.cxx:649
void EndThemePropertiesDlgHdl(sal_Int32 nResult)
Definition: galbrws1.cxx:239
virtual sal_uInt32 GetId() const =0
void ImplExecute(const OString &rIdent)
Definition: galbrws1.cxx:244
OUString aImgNormal
Definition: galbrws1.hxx:53
const OUString & GetStringData() const
Definition: galmisc.hxx:193
Date aThemeChangeDate
Definition: galmisc.hxx:44
void ReleaseTheme(GalleryTheme *pTheme, SfxListener &rListener)
Definition: gallery1.cxx:708
static void ImplFillExchangeData(const GalleryTheme *pThm, ExchangeData &rData)
Definition: galbrws1.cxx:112
OUString aName
SAL_DLLPRIVATE const GalleryThemeEntry * GetThemeInfo(size_t nPos)
Definition: gallery1.hxx:124
INetProtocol GetProtocol() const
RET_OK
IMPL_STATIC_LINK_NOARG(GalleryBrowser1, OnMoreGalleriesClick, weld::Button &, void)
Definition: galbrws1.cxx:375
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
std::unique_ptr< weld::TreeView > mxThemes
Definition: galbrws1.hxx:47
constexpr sal_uInt16 KEY_U
std::unique_ptr< weld::Button > mxNewTheme
Definition: galbrws1.hxx:46
void ImplInsertThemeEntry(const GalleryThemeEntry *pEntry)
Definition: galbrws1.cxx:93
SAL_DLLPRIVATE void SetId(sal_uInt32 nNewId, bool bResetThemeName)
Definition: galtheme.cxx:786
constexpr sal_uInt16 KEY_I
const OUString & GetName() const
Definition: galtheme.cxx:790
constexpr sal_uInt16 KEY_DELETE
IMPL_LINK_NOARG(GalleryBrowser1, SelectThemeHdl, weld::TreeView &, void)
Definition: galbrws1.cxx:473
bool IsReadOnly() const
Definition: galtheme.cxx:787
constexpr sal_uInt16 KEY_INSERT
virtual VclPtr< VclAbstractDialog > CreateGalleryThemePropertiesDialog(weld::Widget *pParent, ExchangeData *pData, SfxItemSet *pItemSet)=0
const OUString & GetThemeName() const
Definition: gallery1.hxx:64
OUString aEditedTitle
Definition: galmisc.hxx:43