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>
41 
42 #include <svx/svxdlg.hxx>
43 #include <memory>
44 #include <bitmaps.hlst>
45 
46 using namespace ::com::sun::star;
47 
49  weld::Builder& rBuilder,
50  Gallery* pGallery,
51  const std::function<void ()>& rThemeSlectionHandler)
52  :
53  mxNewTheme(rBuilder.weld_button("insert")),
54  mxThemes(rBuilder.weld_tree_view("themelist")),
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  maThemeSlectionHandler(rThemeSlectionHandler)
61 {
62  mxNewTheme->set_help_id(HID_GALLERY_NEWTHEME);
63  mxNewTheme->connect_clicked( LINK( this, GalleryBrowser1, ClickNewThemeHdl ) );
64 
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));
71 
72  // disable creation of new themes if a writable directory is not available
73  if( mpGallery->GetUserURL().GetProtocol() == INetProtocol::NotValid )
74  mxNewTheme->set_sensitive(false);
75 
77 
78  for (size_t i = 0, nCount = mpGallery->GetThemeCount(); i < nCount; ++i)
80 }
81 
83 {
85  mpExchangeData.reset();
86 }
87 
89 {
90  static const bool bShowHiddenThemes = ( getenv( "GALLERY_SHOW_HIDDEN_THEMES" ) != nullptr );
91 
92  if( !(pEntry && ( !pEntry->IsHidden() || bShowHiddenThemes )) )
93  return;
94 
95  const OUString* pImage;
96 
97  if( pEntry->IsReadOnly() )
98  pImage = &aImgReadOnly;
99  else if( pEntry->IsDefault() )
100  pImage = &aImgDefault;
101  else
102  pImage = &aImgNormal;
103 
104  mxThemes->append("", pEntry->GetThemeName(), *pImage);
105 }
106 
108 {
109  rData.pTheme = const_cast<GalleryTheme*>(pThm);
110  rData.aEditedTitle = pThm->GetName();
111 
112  try
113  {
114  ::ucbhelper::Content aCnt( pThm->GetThmURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ), uno::Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
115  util::DateTime aDateTimeModified;
116  DateTime aDateTime( DateTime::EMPTY );
117 
118  aCnt.getPropertyValue("DateModified") >>= aDateTimeModified;
119  ::utl::typeConvert( aDateTimeModified, aDateTime );
120  rData.aThemeChangeDate = aDateTime;
121  rData.aThemeChangeTime = aDateTime;
122  }
123  catch( const ucb::ContentCreationException& )
124  {
125  }
126  catch( const uno::RuntimeException& )
127  {
128  }
129  catch( const uno::Exception& )
130  {
131  }
132 }
133 
134 void GalleryBrowser1::ImplGetExecuteVector(std::vector<OString>& o_aExec)
135 {
136  GalleryTheme* pTheme = mpGallery->AcquireTheme( GetSelectedTheme(), *this );
137 
138  if( !pTheme )
139  return;
140 
141  bool bUpdateAllowed, bRenameAllowed, bRemoveAllowed;
142  static const bool bIdDialog = ( getenv( "GALLERY_ENABLE_ID_DIALOG" ) != nullptr );
143 
144  if( pTheme->IsReadOnly() )
145  bUpdateAllowed = bRenameAllowed = bRemoveAllowed = false;
146  else if( pTheme->IsDefault() )
147  {
148  bUpdateAllowed = bRenameAllowed = true;
149  bRemoveAllowed = false;
150  }
151  else
152  bUpdateAllowed = bRenameAllowed = bRemoveAllowed = true;
153 
154  if( bUpdateAllowed && pTheme->GetObjectCount() )
155  o_aExec.emplace_back("update");
156 
157  if( bRenameAllowed )
158  o_aExec.emplace_back("rename");
159 
160  if( bRemoveAllowed )
161  o_aExec.emplace_back("delete");
162 
163  if( bIdDialog && !pTheme->IsReadOnly() )
164  o_aExec.emplace_back("assign");
165 
166  o_aExec.emplace_back("properties");
167 
168  mpGallery->ReleaseTheme( pTheme, *this );
169 }
170 
171 void GalleryBrowser1::ImplGalleryThemeProperties( const OUString & rThemeName, bool bCreateNew )
172 {
173  DBG_ASSERT(!mpThemePropsDlgItemSet, "mpThemePropsDlgItemSet already set!");
174  mpThemePropsDlgItemSet.reset(new SfxItemSet( SfxGetpApp()->GetPool() ));
175  GalleryTheme* pTheme = mpGallery->AcquireTheme( rThemeName, *this );
176 
178 
181 
182  if ( bCreateNew )
183  {
184  xThemePropertiesDialog->StartExecuteAsync([xThemePropertiesDialog, this](sal_Int32 nResult){
186  xThemePropertiesDialog->disposeOnce();
187  });
188  }
189  else
190  {
191  xThemePropertiesDialog->StartExecuteAsync([xThemePropertiesDialog, this](sal_Int32 nResult){
192  EndThemePropertiesDlgHdl(nResult);
193  xThemePropertiesDialog->disposeOnce();
194  });
195  }
196 }
197 
198 void GalleryBrowser1::ImplEndGalleryThemeProperties(bool bCreateNew, sal_Int32 nRet)
199 {
200  if( nRet == RET_OK )
201  {
202  OUString aName( mpExchangeData->pTheme->GetName() );
203 
204  if( !mpExchangeData->aEditedTitle.isEmpty() && aName != mpExchangeData->aEditedTitle )
205  {
206  OUString aTitle( mpExchangeData->aEditedTitle );
207  sal_uInt16 nCount = 0;
208 
209  while( mpGallery->HasTheme( aTitle ) && ( nCount++ < 16000 ) )
210  {
211  aTitle = mpExchangeData->aEditedTitle + " " + OUString::number( nCount );
212  }
213 
214  mpGallery->RenameTheme( aName, aTitle );
215  }
216 
217  if ( bCreateNew )
218  {
219  mxThemes->select_text( mpExchangeData->pTheme->GetName() );
220  SelectThemeHdl( *mxThemes );
221  }
222  }
223 
224  OUString aThemeName( mpExchangeData->pTheme->GetName() );
225  mpGallery->ReleaseTheme( mpExchangeData->pTheme, *this );
226 
227  if ( bCreateNew && ( nRet != RET_OK ) )
228  {
229  mpGallery->RemoveTheme( aThemeName );
230  }
231 }
232 
234 {
235  ImplEndGalleryThemeProperties(true, nResult);
236 }
237 
239 {
240  ImplEndGalleryThemeProperties(false, nResult);
241 }
242 
243 void GalleryBrowser1::ImplExecute(const OString &rIdent)
244 {
245  if (rIdent == "update")
246  {
247  GalleryTheme* pTheme = mpGallery->AcquireTheme( GetSelectedTheme(), *this );
248 
250  ScopedVclPtr<VclAbstractDialog> aActualizeProgress(pFact->CreateActualizeProgressDialog(mxThemes.get(), pTheme));
251 
252  aActualizeProgress->Execute();
253  mpGallery->ReleaseTheme( pTheme, *this );
254  }
255  else if (rIdent == "delete")
256  {
257  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(mxThemes.get(), "svx/ui/querydeletethemedialog.ui"));
258  std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("QueryDeleteThemeDialog"));
259  if (xQuery->run() == RET_YES)
260  mpGallery->RemoveTheme( mxThemes->get_selected_text() );
261  }
262  else if (rIdent == "rename")
263  {
264  GalleryTheme* pTheme = mpGallery->AcquireTheme( GetSelectedTheme(), *this );
265  const OUString aOldName( pTheme->GetName() );
266 
268  ScopedVclPtr<AbstractTitleDialog> aDlg(pFact->CreateTitleDialog(mxThemes.get(), aOldName));
269 
270  if( aDlg->Execute() == RET_OK )
271  {
272  const OUString aNewName( aDlg->GetTitle() );
273 
274  if( !aNewName.isEmpty() && ( aNewName != aOldName ) )
275  {
276  OUString aName( aNewName );
277  sal_uInt16 nCount = 0;
278 
279  while( mpGallery->HasTheme( aName ) && ( nCount++ < 16000 ) )
280  {
281  aName = aNewName + " " + OUString::number( nCount );
282  }
283 
284  mpGallery->RenameTheme( aOldName, aName );
285  }
286  }
287  mpGallery->ReleaseTheme( pTheme, *this );
288  }
289  else if (rIdent == "assign")
290  {
291  GalleryTheme* pTheme = mpGallery->AcquireTheme( GetSelectedTheme(), *this );
292 
293  if (pTheme && !pTheme->IsReadOnly())
294  {
295 
298  if( aDlg->Execute() == RET_OK )
299  pTheme->SetId( aDlg->GetId(), true );
300  }
301 
302  mpGallery->ReleaseTheme( pTheme, *this );
303  }
304  else if (rIdent == "properties")
305  {
307  }
308 }
309 
311 {
312  if (mxNewTheme->get_sensitive())
313  mxNewTheme->grab_focus();
314  else
315  mxThemes->grab_focus();
316 }
317 
319 {
320  const GalleryHint& rGalleryHint = static_cast<const GalleryHint&>(rHint);
321 
322  switch( rGalleryHint.GetType() )
323  {
326  break;
327 
329  {
330  const sal_Int32 nCurSelectPos = mxThemes->get_selected_index();
331  const sal_Int32 nRenameEntryPos = mxThemes->find_text( rGalleryHint.GetThemeName() );
332 
333  mxThemes->remove_text( rGalleryHint.GetThemeName() );
335 
336  if( nCurSelectPos == nRenameEntryPos )
337  {
338  mxThemes->select_text( rGalleryHint.GetStringData() );
339  SelectThemeHdl( *mxThemes );
340  }
341  }
342  break;
343 
345  {
346  mxThemes->remove_text( rGalleryHint.GetThemeName() );
347  }
348  break;
349 
351  {
352  const sal_Int32 nCurSelectPos = mxThemes->get_selected_index();
353  const sal_Int32 nCloseEntryPos = mxThemes->find_text( rGalleryHint.GetThemeName() );
354 
355  if( nCurSelectPos == nCloseEntryPos )
356  {
357  if( nCurSelectPos < ( mxThemes->n_children() - 1 ) )
358  mxThemes->select( nCurSelectPos + 1 );
359  else if( nCurSelectPos )
360  mxThemes->select( nCurSelectPos - 1 );
361  else
362  mxThemes->select(-1);
363 
364  SelectThemeHdl( *mxThemes );
365  }
366  }
367  break;
368 
369  default:
370  break;
371  }
372 }
373 
374 IMPL_LINK(GalleryBrowser1, KeyInputHdl, const KeyEvent&, rKEvt, bool)
375 {
376  bool bRet = false;
377 
378  std::vector<OString> aExecVector;
379  ImplGetExecuteVector(aExecVector);
380  OString sExecuteIdent;
381  bool bMod1 = rKEvt.GetKeyCode().IsMod1();
382 
383  switch( rKEvt.GetKeyCode().GetCode() )
384  {
385  case KEY_INSERT:
386  ClickNewThemeHdl(*mxNewTheme);
387  break;
388 
389  case KEY_I:
390  {
391  if( bMod1 )
392  ClickNewThemeHdl(*mxNewTheme);
393  }
394  break;
395 
396  case KEY_U:
397  {
398  if( bMod1 )
399  sExecuteIdent = "update";
400  }
401  break;
402 
403  case KEY_DELETE:
404  sExecuteIdent = "delete";
405  break;
406 
407  case KEY_D:
408  {
409  if( bMod1 )
410  sExecuteIdent = "delete";
411  }
412  break;
413 
414  case KEY_R:
415  {
416  if( bMod1 )
417  sExecuteIdent = "rename";
418  }
419  break;
420 
421  case KEY_RETURN:
422  {
423  if( bMod1 )
424  sExecuteIdent = "properties";
425  }
426  break;
427  }
428 
429  if (!sExecuteIdent.isEmpty() && (std::find( aExecVector.begin(), aExecVector.end(), sExecuteIdent) != aExecVector.end()))
430  {
431  ImplExecute(sExecuteIdent);
432  bRet = true;
433  }
434 
435  return bRet;
436 }
437 
438 IMPL_LINK(GalleryBrowser1, PopupMenuHdl, const CommandEvent&, rCEvt, bool)
439 {
440  if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
441  return false;
442 
443  std::vector<OString> aExecVector;
444  ImplGetExecuteVector(aExecVector);
445 
446  if (aExecVector.empty())
447  return true;
448 
449  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(mxThemes.get(), "svx/ui/gallerymenu1.ui"));
450  std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("menu"));
451 
452  xMenu->set_visible("update", std::find( aExecVector.begin(), aExecVector.end(), "update" ) != aExecVector.end());
453  xMenu->set_visible("rename", std::find( aExecVector.begin(), aExecVector.end(), "rename" ) != aExecVector.end());
454  xMenu->set_visible("delete", std::find( aExecVector.begin(), aExecVector.end(), "delete" ) != aExecVector.end());
455  xMenu->set_visible("assign", std::find( aExecVector.begin(), aExecVector.end(), "assign" ) != aExecVector.end());
456  xMenu->set_visible("properties", std::find( aExecVector.begin(), aExecVector.end(), "properties" ) != aExecVector.end());
457 
458  OString sCommand(xMenu->popup_at_rect(mxThemes.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1))));
459  ImplExecute(sCommand);
460 
461  return true;
462 }
463 
465 {
466  if (maThemeSlectionHandler)
467  maThemeSlectionHandler();
468 }
469 
470 IMPL_LINK_NOARG(GalleryBrowser1, ClickNewThemeHdl, weld::Button&, void)
471 {
472  OUString aNewTheme( SvxResId(RID_SVXSTR_GALLERY_NEWTHEME) );
473  OUString aName( aNewTheme );
474  sal_uInt16 nCount = 0;
475 
476  while( mpGallery->HasTheme( aName ) && ( nCount++ < 16000 ) )
477  {
478  aName = aNewTheme + " " + OUString::number( nCount );
479  }
480 
481  if( !mpGallery->HasTheme( aName ) && mpGallery->CreateTheme( aName ) )
482  {
483  ImplGalleryThemeProperties( aName, true );
484  }
485 }
486 
487 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: galbrws1.cxx:318
bool IsDefault() const
Definition: galtheme.cxx:882
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:704
void GrabFocus()
Definition: galbrws1.cxx:310
static SvxAbstractDialogFactory * Create()
Definition: svxdlg.cxx:23
void ImplEndGalleryThemeProperties(bool bCreateNew, sal_Int32 nResult)
Definition: galbrws1.cxx:198
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:134
bool IsReadOnly() const
Definition: gallery1.hxx:69
virtual short Execute()=0
OUString aImgDefault
Definition: galbrws1.hxx:53
IMPL_LINK(GalleryBrowser1, KeyInputHdl, const KeyEvent &, rKEvt, bool)
Definition: galbrws1.cxx:374
SfxApplication * SfxGetpApp()
size_t GetThemeCount() const
Definition: gallery1.hxx:119
RET_YES
OUString aImgReadOnly
Definition: galbrws1.hxx:54
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:28
std::unique_ptr< ExchangeData > mpExchangeData
Definition: galbrws1.hxx:49
GalleryBrowser1(weld::Builder &rBuilder, Gallery *pGallery, const ::std::function< void()> &rThemeSlectionHandler)
Definition: galbrws1.cxx:48
void RenameTheme(const OUString &rOldName, const OUString &rNewName)
Definition: gallery1.cxx:581
constexpr sal_uInt16 KEY_D
int nCount
const OUString & GetThemeName() const
Definition: galmisc.hxx:192
bool RemoveTheme(const OUString &rThemeName)
Definition: gallery1.cxx:604
bool IsHidden() const
Definition: gallery1.hxx:72
constexpr sal_uInt16 KEY_R
Gallery * mpGallery
Definition: galbrws1.hxx:48
GalleryHintType GetType() const
Definition: galmisc.hxx:191
void EndNewThemePropertiesDlgHdl(sal_Int32 nResult)
Definition: galbrws1.cxx:233
SAL_DLLPRIVATE const INetURLObject & GetUserURL() const
Definition: gallery1.hxx:136
#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:85
void ImplGalleryThemeProperties(const OUString &rThemeName, bool bCreateNew)
Definition: galbrws1.cxx:171
SAL_DLLPRIVATE sal_uInt32 GetObjectCount() const
Definition: galtheme.hxx:104
std::unique_ptr< SfxItemSet > mpThemePropsDlgItemSet
Definition: galbrws1.hxx:50
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:729
bool HasTheme(const OUString &rThemeName)
Definition: gallery1.cxx:555
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
void EndThemePropertiesDlgHdl(sal_Int32 nResult)
Definition: galbrws1.cxx:238
virtual sal_uInt32 GetId() const =0
void ImplExecute(const OString &rIdent)
Definition: galbrws1.cxx:243
OUString aImgNormal
Definition: galbrws1.hxx:52
const OUString & GetStringData() const
Definition: galmisc.hxx:193
Date aThemeChangeDate
Definition: galmisc.hxx:44
void ReleaseTheme(GalleryTheme *pTheme, SfxListener &rListener)
Definition: gallery1.cxx:718
static void ImplFillExchangeData(const GalleryTheme *pThm, ExchangeData &rData)
Definition: galbrws1.cxx:107
OUString aName
SAL_DLLPRIVATE const GalleryThemeEntry * GetThemeInfo(size_t nPos)
Definition: gallery1.hxx:120
INetProtocol GetProtocol() const
RET_OK
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
Reference< XComponentContext > getProcessComponentContext()
std::unique_ptr< weld::TreeView > mxThemes
Definition: galbrws1.hxx:47
SAL_DLLPRIVATE const INetURLObject & GetThmURL() const
Definition: galtheme.cxx:875
constexpr sal_uInt16 KEY_U
std::unique_ptr< weld::Button > mxNewTheme
Definition: galbrws1.hxx:46
void ImplInsertThemeEntry(const GalleryThemeEntry *pEntry)
Definition: galbrws1.cxx:88
SAL_DLLPRIVATE void SetId(sal_uInt32 nNewId, bool bResetThemeName)
Definition: galtheme.cxx:880
constexpr sal_uInt16 KEY_I
const OUString & GetName() const
Definition: galtheme.cxx:884
constexpr sal_uInt16 KEY_DELETE
IMPL_LINK_NOARG(GalleryBrowser1, SelectThemeHdl, weld::TreeView &, void)
Definition: galbrws1.cxx:464
bool IsReadOnly() const
Definition: galtheme.cxx:881
constexpr sal_uInt16 KEY_INSERT
virtual VclPtr< VclAbstractDialog > CreateGalleryThemePropertiesDialog(weld::Widget *pParent, ExchangeData *pData, SfxItemSet *pItemSet)=0
const OUString & GetThemeName() const
Definition: gallery1.hxx:62
OUString aEditedTitle
Definition: galmisc.hxx:43