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 
10 #include <sfx2/templatedlg.hxx>
11 
12 #include <sfx2/inputdlg.hxx>
13 #include <sfx2/module.hxx>
14 #include <templatesearchview.hxx>
15 #include <templatesearchviewitem.hxx>
16 
17 #include <comphelper/processfactory.hxx>
18 #include <comphelper/string.hxx>
19 #include <comphelper/storagehelper.hxx>
20 #include <sfx2/app.hxx>
21 #include <sfx2/docfac.hxx>
22 #include <sfx2/docfilt.hxx>
23 #include <sfx2/fcontnr.hxx>
24 #include <sfx2/filedlghelper.hxx>
25 #include <sfx2/objsh.hxx>
26 #include <sfx2/sfxresid.hxx>
27 #include <sfx2/templatedlglocalview.hxx>
28 #include <templatecontaineritem.hxx>
29 #include <templateviewitem.hxx>
30 #include <sfx2/thumbnailviewitem.hxx>
31 #include <sot/storage.hxx>
32 #include <svtools/imagemgr.hxx>
33 #include <tools/urlobj.hxx>
34 #include <unotools/moduleoptions.hxx>
35 #include <unotools/pathoptions.hxx>
36 #include <unotools/viewoptions.hxx>
37 #include <vcl/event.hxx>
38 #include <vcl/mnemonic.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/weld.hxx>
41 
42 #include <com/sun/star/beans/NamedValue.hpp>
43 #include <com/sun/star/beans/PropertyValue.hpp>
44 #include <com/sun/star/document/MacroExecMode.hpp>
45 #include <com/sun/star/document/UpdateDocMode.hpp>
46 #include <com/sun/star/embed/XStorage.hpp>
47 #include <com/sun/star/embed/ElementModes.hpp>
48 #include <com/sun/star/frame/Desktop.hpp>
49 #include <com/sun/star/frame/XStorable.hpp>
50 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
51 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
52 #include <com/sun/star/ui/dialogs/FolderPicker.hpp>
53 #include <com/sun/star/task/InteractionHandler.hpp>
54 #include <comphelper/dispatchcommand.hxx>
55 
56 #include <sfx2/strings.hrc>
57 
58 constexpr OUStringLiteral TM_SETTING_MANAGER = u"TemplateManager";
59 constexpr OUStringLiteral TM_SETTING_LASTFOLDER = u"LastFolder";
60 constexpr OUStringLiteral TM_SETTING_LASTAPPLICATION = u"LastApplication";
61 constexpr OUStringLiteral TM_SETTING_VIEWMODE = u"ViewMode";
62 
63 #define MNI_ACTION_NEW_FOLDER "new"
64 #define MNI_ACTION_RENAME_FOLDER "rename"
65 #define MNI_ACTION_DELETE_FOLDER "delete"
66 #define MNI_ACTION_REFRESH   "refresh"
67 #define MNI_ACTION_DEFAULT   "default"
68 #define MNI_WRITER           1
69 #define MNI_CALC             2
70 #define MNI_IMPRESS          3
71 #define MNI_DRAW             4
72 
73 using namespace ::com::sun::star;
74 using namespace ::com::sun::star::beans;
75 using namespace ::com::sun::star::embed;
76 using namespace ::com::sun::star::frame;
77 using namespace ::com::sun::star::lang;
78 using namespace ::com::sun::star::uno;
79 using namespace ::com::sun::star::ui::dialogs;
80 using namespace ::com::sun::star::document;
81 
82 static bool lcl_getServiceName (const OUString &rFileURL, OUString &rName );
83 
84 static std::vector<OUString> lcl_getAllFactoryURLs ();
85 
86 namespace {
87 
88 class SearchView_Keyword
89 {
90 public:
91 
SearchView_Keyword(const OUString & rKeyword,FILTER_APPLICATION App)92     SearchView_Keyword (const OUString &rKeyword, FILTER_APPLICATION App)
93         : maKeyword(rKeyword.toAsciiLowerCase()), meApp(App)
94     {}
95 
operator ()(const TemplateItemProperties & rItem)96     bool operator() (const TemplateItemProperties &rItem)
97     {
98         bool bRet = true;
99 
100         INetURLObject aUrl(rItem.aPath);
101         OUString aExt = aUrl.getExtension();
102 
103         if (meApp == FILTER_APPLICATION::WRITER)
104         {
105             bRet = aExt == "ott" || aExt == "stw" || aExt == "oth" || aExt == "dot" || aExt == "dotx";
106         }
107         else if (meApp == FILTER_APPLICATION::CALC)
108         {
109             bRet = aExt == "ots" || aExt == "stc" || aExt == "xlt" || aExt == "xltm" || aExt == "xltx";
110         }
111         else if (meApp == FILTER_APPLICATION::IMPRESS)
112         {
113             bRet = aExt == "otp" || aExt == "sti" || aExt == "pot" || aExt == "potm" || aExt == "potx";
114         }
115         else if (meApp == FILTER_APPLICATION::DRAW)
116         {
117             bRet = aExt == "otg" || aExt == "std";
118         }
119 
120         return bRet && MatchSubstring(rItem.aName);
121     }
122 
MatchSubstring(OUString const & sItemName)123     bool MatchSubstring( OUString const & sItemName )
124     {
125         if(maKeyword.isEmpty())
126             return false;
127         return sItemName.toAsciiLowerCase().indexOf(maKeyword) >= 0;
128     }
129 
130 private:
131 
132     OUString maKeyword;
133     FILTER_APPLICATION meApp;
134 };
135 
136 }
137 
138 /***
139  *
140  * Order items in ascending order (useful for the selection sets and move/copy operations since the associated ids
141  * change when processed by the SfxDocumentTemplates class so we want to process to ones with higher id first)
142  *
143  ***/
144 
cmpSelectionItems(const ThumbnailViewItem * pItem1,const ThumbnailViewItem * pItem2)145 static bool cmpSelectionItems (const ThumbnailViewItem *pItem1, const ThumbnailViewItem *pItem2)
146 {
147     return pItem1->mnId > pItem2->mnId;
148 }
149 
SfxTemplateManagerDlg(weld::Window * pParent)150 SfxTemplateManagerDlg::SfxTemplateManagerDlg(weld::Window *pParent)
151     : GenericDialogController(pParent, "sfx/ui/templatedlg.ui", "TemplateDialog")
152     , maSelTemplates(cmpSelectionItems)
153     , mxDesktop(Desktop::create(comphelper::getProcessComponentContext()))
154     , m_aUpdateDataTimer("UpdateDataTimer")
155     , mxSearchFilter(m_xBuilder->weld_entry("search_filter"))
156     , mxCBApp(m_xBuilder->weld_combo_box("filter_application"))
157     , mxCBFolder(m_xBuilder->weld_combo_box("filter_folder"))
158     , mxOKButton(m_xBuilder->weld_button("ok"))
159     , mxMoveButton(m_xBuilder->weld_button("move_btn"))
160     , mxExportButton(m_xBuilder->weld_button("export_btn"))
161     , mxImportButton(m_xBuilder->weld_button("import_btn"))
162     , mxMoreTemplatesButton(m_xBuilder->weld_button("btnMoreTemplates"))
163     , mxCBXHideDlg(m_xBuilder->weld_check_button("hidedialogcb"))
164     , mxActionBar(m_xBuilder->weld_menu_button("action_menu"))
165     , mxSearchView(new TemplateSearchView(m_xBuilder->weld_scrolled_window("scrollsearch", true),
166                                           m_xBuilder->weld_menu("contextmenu1"),
167                                           m_xBuilder->weld_tree_view("treesearch_list")))
168     , mxLocalView(new TemplateDlgLocalView(m_xBuilder->weld_scrolled_window("scrolllocal", true),
169                                            m_xBuilder->weld_menu("contextmenu2"),
170                                            m_xBuilder->weld_tree_view("tree_list")))
171     , mxTemplateDefaultMenu(m_xBuilder->weld_menu("submenu"))
172     , mxSearchViewWeld(new weld::CustomWeld(*m_xBuilder, "search_view", *mxSearchView))
173     , mxLocalViewWeld(new weld::CustomWeld(*m_xBuilder, "template_view", *mxLocalView))
174     , mxListViewButton(m_xBuilder->weld_toggle_button("list_view_btn"))
175     , mxThumbnailViewButton(m_xBuilder->weld_toggle_button("thumbnail_view_btn"))
176     , mViewMode(TemplateViewMode::eThumbnailView)
177 {
178     // Create popup menus
179     mxActionBar->insert_item(0, MNI_ACTION_NEW_FOLDER, SfxResId(STR_CATEGORY_NEW), nullptr, nullptr, TRISTATE_INDET);
180     mxActionBar->insert_item(1, MNI_ACTION_RENAME_FOLDER, SfxResId(STR_CATEGORY_RENAME), nullptr, nullptr, TRISTATE_INDET);
181     mxActionBar->insert_item(2, MNI_ACTION_DELETE_FOLDER, SfxResId(STR_CATEGORY_DELETE), nullptr, nullptr, TRISTATE_INDET);
182     mxActionBar->insert_separator(3, "separator");
183     mxActionBar->insert_item(4, MNI_ACTION_REFRESH, SfxResId(STR_ACTION_REFRESH), nullptr, nullptr, TRISTATE_INDET);
184     mxActionBar->connect_selected(LINK(this,SfxTemplateManagerDlg,MenuSelectHdl));
185 
186     mxLocalView->setItemMaxTextLength(TEMPLATE_ITEM_MAX_TEXT_LENGTH);
187     mxLocalView->setItemDimensions(TEMPLATE_ITEM_MAX_WIDTH,TEMPLATE_ITEM_THUMBNAIL_MAX_HEIGHT,
188                               TEMPLATE_ITEM_MAX_HEIGHT-TEMPLATE_ITEM_THUMBNAIL_MAX_HEIGHT,
189                               TEMPLATE_ITEM_PADDING);
190 
191     mxLocalView->setItemStateHdl(LINK(this,SfxTemplateManagerDlg,TVItemStateHdl));
192     mxLocalView->setCreateContextMenuHdl(LINK(this,SfxTemplateManagerDlg, CreateContextMenuHdl));
193     mxLocalView->setOpenRegionHdl(LINK(this,SfxTemplateManagerDlg, OpenRegionHdl));
194     mxLocalView->setOpenTemplateHdl(LINK(this,SfxTemplateManagerDlg, OpenTemplateHdl));
195     mxLocalView->setEditTemplateHdl(LINK(this,SfxTemplateManagerDlg, EditTemplateHdl));
196     mxLocalView->setDeleteTemplateHdl(LINK(this,SfxTemplateManagerDlg, DeleteTemplateHdl));
197     mxLocalView->setDefaultTemplateHdl(LINK(this,SfxTemplateManagerDlg, DefaultTemplateHdl));
198 
199     mxSearchView->setItemMaxTextLength(TEMPLATE_ITEM_MAX_TEXT_LENGTH);
200 
201     mxSearchView->setItemDimensions(TEMPLATE_ITEM_MAX_WIDTH,TEMPLATE_ITEM_THUMBNAIL_MAX_HEIGHT,
202                                     TEMPLATE_ITEM_MAX_HEIGHT_SUB-TEMPLATE_ITEM_THUMBNAIL_MAX_HEIGHT,
203                                     TEMPLATE_ITEM_PADDING);
204 
205     mxSearchView->setItemStateHdl(LINK(this,SfxTemplateManagerDlg,TVItemStateHdl));
206     mxSearchView->setCreateContextMenuHdl(LINK(this,SfxTemplateManagerDlg, CreateContextMenuHdl));
207     mxSearchView->setOpenTemplateHdl(LINK(this,SfxTemplateManagerDlg,OpenTemplateHdl));
208     mxSearchView->setEditTemplateHdl(LINK(this,SfxTemplateManagerDlg, EditTemplateHdl));
209     mxSearchView->setDeleteTemplateHdl(LINK(this,SfxTemplateManagerDlg, DeleteTemplateHdl));
210     mxSearchView->setDefaultTemplateHdl(LINK(this,SfxTemplateManagerDlg, DefaultTemplateHdl));
211 
212     mxLocalView->ShowTooltips(true);
213     mxSearchView->ShowTooltips(true);
214 
215     mxOKButton->connect_clicked(LINK(this, SfxTemplateManagerDlg, OkClickHdl));
216     mxMoveButton->connect_clicked(LINK(this, SfxTemplateManagerDlg, MoveClickHdl));
217     mxExportButton->connect_clicked(LINK(this, SfxTemplateManagerDlg, ExportClickHdl));
218     mxImportButton->connect_clicked(LINK(this, SfxTemplateManagerDlg, ImportClickHdl));
219     // FIXME: rather than disabling make dispatchCommand(".uno:AdditionsDialog") work in start center
220     if ( !SfxModule::GetActiveModule() )
221         mxMoreTemplatesButton->set_sensitive(false);
222     else
223         mxMoreTemplatesButton->connect_clicked(LINK(this, SfxTemplateManagerDlg, LinkClickHdl));
224     mxListViewButton->connect_toggled(LINK(this, SfxTemplateManagerDlg, ListViewHdl));
225     mxThumbnailViewButton->connect_toggled(LINK(this, SfxTemplateManagerDlg, ThumbnailViewHdl));
226 
227     mxSearchFilter->connect_changed(LINK(this, SfxTemplateManagerDlg, SearchUpdateHdl));
228     mxSearchFilter->connect_focus_in(LINK( this, SfxTemplateManagerDlg, GetFocusHdl ));
229     mxSearchFilter->connect_focus_out(LINK( this, SfxTemplateManagerDlg, LoseFocusHdl ));
230     mxSearchFilter->connect_key_press(LINK( this, SfxTemplateManagerDlg, KeyInputHdl));
231 
232     mxActionBar->show();
233 
234     createDefaultTemplateMenu();
235 
236     mxLocalView->Populate();
237     mxLocalView->filterItems(ViewFilter_Application(FILTER_APPLICATION::NONE));
238 
239     mxCBApp->set_active(0);
240     fillFolderComboBox();
241 
242     mxExportButton->set_sensitive(false);
243     mxMoveButton->set_sensitive(false);
244     mxOKButton->set_label(SfxResId(STR_OPEN));
245 
246     mxCBApp->connect_changed(LINK(this, SfxTemplateManagerDlg, SelectApplicationHdl));
247     mxCBFolder->connect_changed(LINK(this, SfxTemplateManagerDlg, SelectRegionHdl));
248 
249     mxLocalView->Show();
250 
251     m_aUpdateDataTimer.SetInvokeHandler(LINK(this, SfxTemplateManagerDlg, ImplUpdateDataHdl));
252     m_aUpdateDataTimer.SetDebugName( "SfxTemplateManagerDlg UpdateDataTimer" );
253     m_aUpdateDataTimer.SetTimeout(EDIT_UPDATEDATA_TIMEOUT);
254 
255     mxLocalView->connect_focus_rect(LINK(this, SfxTemplateManagerDlg, FocusRectLocalHdl));
256     mxSearchView->connect_focus_rect(LINK(this, SfxTemplateManagerDlg, FocusRectSearchHdl));
257     bMakeSelItemVisible = false;
258 }
259 
~SfxTemplateManagerDlg()260 SfxTemplateManagerDlg::~SfxTemplateManagerDlg()
261 {
262     writeSettings();
263 
264     // Ignore view events since we are cleaning the object
265     mxLocalView->setItemStateHdl(Link<const ThumbnailViewItem*,void>());
266     mxLocalView->setOpenRegionHdl(Link<void*,void>());
267     mxLocalView->setOpenTemplateHdl(Link<ThumbnailViewItem*, void>());
268     mxSearchView->setItemStateHdl(Link<const ThumbnailViewItem*,void>());
269     mxSearchView->setOpenTemplateHdl(Link<ThumbnailViewItem*, void>());
270 }
271 
run()272 short SfxTemplateManagerDlg::run()
273 {
274     //use application specific settings if there's no previous setting
275     getApplicationSpecificSettings();
276     readSettings();
277 
278     return weld::GenericDialogController::run();
279 }
280 
IMPL_LINK(SfxTemplateManagerDlg,KeyInputHdl,const KeyEvent &,rKeyEvent,bool)281 IMPL_LINK(SfxTemplateManagerDlg, KeyInputHdl, const KeyEvent&, rKeyEvent, bool)
282 {
283     if (mxSearchFilter != nullptr && !mxSearchFilter->get_text().isEmpty())
284     {
285         vcl::KeyCode    aKeyCode = rKeyEvent.GetKeyCode();
286         sal_uInt16      nKeyCode = aKeyCode.GetCode();
287 
288         if ( nKeyCode == KEY_ESCAPE )
289         {
290             mxSearchFilter->set_text("");
291             SearchUpdateHdl(*mxSearchFilter);
292             return true;
293         }
294     }
295     return false;
296 }
297 
setDocumentModel(const uno::Reference<frame::XModel> & rModel)298 void SfxTemplateManagerDlg::setDocumentModel(const uno::Reference<frame::XModel> &rModel)
299 {
300     m_xModel = rModel;
301 }
302 
setTemplateViewMode(TemplateViewMode eViewMode)303 void SfxTemplateManagerDlg::setTemplateViewMode(TemplateViewMode eViewMode)
304 {
305     mViewMode = eViewMode;
306     mxLocalView->setTemplateViewMode(eViewMode);
307     mxSearchView->setTemplateViewMode(eViewMode);
308     if ( mViewMode == TemplateViewMode::eListView)
309     {
310         mxThumbnailViewButton->set_active(false);
311         mxListViewButton->set_active(true);
312     }
313     else
314     {
315         mxThumbnailViewButton->set_active(true);
316         mxListViewButton->set_active(false);
317     }
318 
319     if (! mxSearchFilter->get_text().isEmpty())
320     {
321         mxSearchView->Show();
322         mxLocalView->Hide();
323     }
324     else
325     {
326         mxSearchView->Hide();
327         mxLocalView->Show();
328     }
329 }
330 
getTemplateViewMode() const331 TemplateViewMode SfxTemplateManagerDlg::getTemplateViewMode() const
332 {
333     return mViewMode;
334 }
335 
336 
getCurrentApplicationFilter() const337 FILTER_APPLICATION SfxTemplateManagerDlg::getCurrentApplicationFilter() const
338 {
339     const sal_Int16 nCurAppId = mxCBApp->get_active();
340 
341     if (nCurAppId == MNI_WRITER)
342         return FILTER_APPLICATION::WRITER;
343     else if (nCurAppId == MNI_IMPRESS)
344         return FILTER_APPLICATION::IMPRESS;
345     else if (nCurAppId == MNI_CALC)
346         return FILTER_APPLICATION::CALC;
347     else if (nCurAppId == MNI_DRAW)
348         return FILTER_APPLICATION::DRAW;
349 
350     return FILTER_APPLICATION::NONE;
351 }
352 
fillFolderComboBox()353 void SfxTemplateManagerDlg::fillFolderComboBox()
354 {
355     std::vector<OUString> aFolderNames = mxLocalView->getFolderNames();
356 
357     for (size_t i = 0, n = aFolderNames.size(); i < n; ++i)
358         mxCBFolder->append_text(aFolderNames[i]);
359     mxCBFolder->set_active(0);
360     mxActionBar->set_item_visible(MNI_ACTION_RENAME_FOLDER, false);
361 }
362 
getApplicationSpecificSettings()363 void SfxTemplateManagerDlg::getApplicationSpecificSettings()
364 {
365     if ( ! m_xModel.is() )
366     {
367         mxCBApp->set_active(0);
368         mxCBFolder->set_active(0);
369         mxActionBar->set_item_visible(MNI_ACTION_RENAME_FOLDER, false);
370         mxLocalView->filterItems(ViewFilter_Application(getCurrentApplicationFilter()));
371         mxLocalView->showAllTemplates();
372         return;
373     }
374 
375     SvtModuleOptions::EFactory eFactory = SvtModuleOptions::ClassifyFactoryByModel(m_xModel);
376 
377     switch(eFactory)
378     {
379         case SvtModuleOptions::EFactory::WRITER:
380         case SvtModuleOptions::EFactory::WRITERWEB:
381         case SvtModuleOptions::EFactory::WRITERGLOBAL:
382                             mxCBApp->set_active(MNI_WRITER);
383                             break;
384         case SvtModuleOptions::EFactory::CALC:
385                             mxCBApp->set_active(MNI_CALC);
386                             break;
387         case SvtModuleOptions::EFactory::IMPRESS:
388                             mxCBApp->set_active(MNI_IMPRESS);
389                             break;
390         case SvtModuleOptions::EFactory::DRAW:
391                             mxCBApp->set_active(MNI_DRAW);
392                             break;
393         default:
394                 mxCBApp->set_active(0);
395                 break;
396     }
397 
398     mxLocalView->filterItems(ViewFilter_Application(getCurrentApplicationFilter()));
399     mxCBFolder->set_active(0);
400     mxActionBar->set_item_visible(MNI_ACTION_RENAME_FOLDER, false);
401     mxLocalView->showAllTemplates();
402 }
403 
readSettings()404 void SfxTemplateManagerDlg::readSettings ()
405 {
406     OUString aLastFolder;
407     SvtViewOptions aViewSettings( EViewType::Dialog, TM_SETTING_MANAGER );
408     sal_Int16 nViewMode = -1;
409 
410     if ( aViewSettings.Exists() )
411     {
412         sal_uInt16 nTmp = 0;
413         aViewSettings.GetUserItem(TM_SETTING_LASTFOLDER) >>= aLastFolder;
414         aViewSettings.GetUserItem(TM_SETTING_LASTAPPLICATION) >>= nTmp;
415         aViewSettings.GetUserItem(TM_SETTING_VIEWMODE) >>= nViewMode;
416 
417         //open last remembered application only when application model is not set
418         if(!m_xModel.is())
419         {
420             switch (nTmp)
421             {
422                 case MNI_WRITER:
423                     mxCBApp->set_active(MNI_WRITER);
424                     break;
425                 case MNI_CALC:
426                     mxCBApp->set_active(MNI_CALC);
427                     break;
428                 case MNI_IMPRESS:
429                     mxCBApp->set_active(MNI_IMPRESS);
430                     break;
431                 case MNI_DRAW:
432                     mxCBApp->set_active(MNI_DRAW);
433                     break;
434                 default:
435                     mxCBApp->set_active(0);
436                     break;
437             }
438         }
439     }
440 
441     mxLocalView->filterItems(ViewFilter_Application(getCurrentApplicationFilter()));
442 
443     if (aLastFolder.isEmpty())
444     {
445         //show all categories
446         mxCBFolder->set_active(0);
447         mxActionBar->set_item_visible(MNI_ACTION_RENAME_FOLDER, false);
448         mxLocalView->showAllTemplates();
449     }
450     else
451     {
452         mxCBFolder->set_active_text(aLastFolder);
453         mxLocalView->showRegion(aLastFolder);
454         mxActionBar->set_item_visible(MNI_ACTION_RENAME_FOLDER, true);
455     }
456 
457     if(nViewMode == static_cast<sal_Int16>(TemplateViewMode::eListView) ||
458         nViewMode == static_cast<sal_Int16>(TemplateViewMode::eThumbnailView))
459     {
460         TemplateViewMode eViewMode = static_cast<TemplateViewMode>(nViewMode);
461         setTemplateViewMode(eViewMode);
462     }
463     else
464     {
465         //Default ViewMode
466         setTemplateViewMode(TemplateViewMode::eThumbnailView);
467     }
468 }
469 
writeSettings()470 void SfxTemplateManagerDlg::writeSettings ()
471 {
472     OUString aLastFolder;
473 
474     if (mxLocalView->getCurRegionId())
475         aLastFolder = mxLocalView->getRegionName(mxLocalView->getCurRegionId()-1);
476 
477     // last folder
478     Sequence< NamedValue > aSettings
479     {
480         { TM_SETTING_LASTFOLDER, css::uno::makeAny(aLastFolder) },
481         { TM_SETTING_LASTAPPLICATION,     css::uno::makeAny(sal_uInt16(mxCBApp->get_active())) },
482         { TM_SETTING_VIEWMODE, css::uno::makeAny(static_cast<sal_Int16>(getTemplateViewMode()))}
483     };
484 
485     // write
486     SvtViewOptions aViewSettings(EViewType::Dialog, TM_SETTING_MANAGER);
487     aViewSettings.SetUserData(aSettings);
488 }
489 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,SelectApplicationHdl,weld::ComboBox &,void)490 IMPL_LINK_NOARG(SfxTemplateManagerDlg, SelectApplicationHdl, weld::ComboBox&, void)
491 {
492     if (mxLocalView->IsVisible())
493     {
494         mxLocalView->filterItems(ViewFilter_Application(getCurrentApplicationFilter()));
495         mxLocalView->showAllTemplates();
496         mxCBFolder->set_active(0);
497         mxActionBar->set_item_visible(MNI_ACTION_RENAME_FOLDER, false);
498     }
499     if (mxSearchView->IsVisible())
500         SearchUpdate();
501 }
502 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,SelectRegionHdl,weld::ComboBox &,void)503 IMPL_LINK_NOARG(SfxTemplateManagerDlg, SelectRegionHdl, weld::ComboBox&, void)
504 {
505     const OUString sSelectedRegion = mxCBFolder->get_active_text();
506 
507     if(mxCBFolder->get_active() == 0)
508     {
509         mxLocalView->showAllTemplates();
510         mxActionBar->set_item_visible(MNI_ACTION_RENAME_FOLDER, false);
511     }
512     else
513     {
514         mxLocalView->showRegion(sSelectedRegion);
515         mxActionBar->set_item_visible(MNI_ACTION_RENAME_FOLDER, true);
516     }
517     if (mxSearchView->IsVisible())
518         SearchUpdate();
519 }
520 
IMPL_LINK(SfxTemplateManagerDlg,TVItemStateHdl,const ThumbnailViewItem *,pItem,void)521 IMPL_LINK(SfxTemplateManagerDlg, TVItemStateHdl, const ThumbnailViewItem*, pItem, void)
522 {
523     const TemplateViewItem *pViewItem = dynamic_cast<const TemplateViewItem*>(pItem);
524 
525     if (pViewItem)
526         OnTemplateState(pItem);
527 }
528 
IMPL_LINK(SfxTemplateManagerDlg,MenuSelectHdl,const OString &,rIdent,void)529 IMPL_LINK(SfxTemplateManagerDlg, MenuSelectHdl, const OString&, rIdent, void)
530 {
531     if (rIdent == MNI_ACTION_NEW_FOLDER)
532         OnCategoryNew();
533     else if (rIdent == MNI_ACTION_RENAME_FOLDER)
534         OnCategoryRename();
535     else if (rIdent == MNI_ACTION_DELETE_FOLDER)
536         OnCategoryDelete();
537     else if (rIdent == MNI_ACTION_REFRESH)
538     {
539         mxLocalView->reload();
540         if(mxSearchView->IsVisible())
541             SearchUpdateHdl(*mxSearchFilter);
542     }
543     else if (rIdent != MNI_ACTION_DEFAULT)
544         DefaultTemplateMenuSelectHdl(rIdent);
545 }
546 
DefaultTemplateMenuSelectHdl(std::string_view rIdent)547 void SfxTemplateManagerDlg::DefaultTemplateMenuSelectHdl(std::string_view rIdent)
548 {
549     OUString aServiceName = SfxObjectShell::GetServiceNameFromFactory(OUString::fromUtf8(rIdent));
550 
551     OUString sPrevDefault = SfxObjectFactory::GetStandardTemplate( aServiceName );
552     if(!sPrevDefault.isEmpty())
553     {
554         if(mxSearchView->IsVisible())
555             mxSearchView->RemoveDefaultTemplateIcon(sPrevDefault);
556         else
557             mxLocalView->RemoveDefaultTemplateIcon(sPrevDefault);
558     }
559 
560     SfxObjectFactory::SetStandardTemplate( aServiceName, OUString() );
561     if (mxSearchView->IsVisible())
562         mxSearchView->refreshDefaultColumn();
563     else
564         mxLocalView->refreshDefaultColumn();
565     createDefaultTemplateMenu();
566 }
567 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,OkClickHdl,weld::Button &,void)568 IMPL_LINK_NOARG(SfxTemplateManagerDlg, OkClickHdl, weld::Button&, void)
569 {
570    OnTemplateOpen();
571    m_xDialog->response(RET_OK);
572 }
573 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,MoveClickHdl,weld::Button &,void)574 IMPL_LINK_NOARG(SfxTemplateManagerDlg, MoveClickHdl, weld::Button&, void)
575 {
576     // modal dialog to select templates category
577     SfxTemplateCategoryDialog aDlg(m_xDialog.get());
578     aDlg.SetCategoryLBEntries(mxLocalView->getFolderNames());
579 
580     size_t nItemId = 0;
581 
582     if (aDlg.run() == RET_OK)
583     {
584         const OUString& sCategory = aDlg.GetSelectedCategory();
585         bool bIsNewCategory = aDlg.IsNewCategoryCreated();
586         if(bIsNewCategory)
587         {
588             if (!sCategory.isEmpty())
589             {
590                 nItemId = mxLocalView->createRegion(sCategory);
591                 if(nItemId)
592                     mxCBFolder->append_text(sCategory);
593             }
594         }
595         else
596             nItemId = mxLocalView->getRegionId(sCategory);
597     }
598 
599     if(nItemId)
600     {
601         if (mxSearchView->IsVisible())
602             localSearchMoveTo(nItemId);
603         else
604             localMoveTo(nItemId);
605     }
606 
607     mxLocalView->reload();
608     if (mxSearchView->IsVisible())
609         SearchUpdate();
610 }
611 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,ExportClickHdl,weld::Button &,void)612 IMPL_LINK_NOARG(SfxTemplateManagerDlg, ExportClickHdl, weld::Button&, void)
613 {
614     OnTemplateExport();
615 }
616 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,ImportClickHdl,weld::Button &,void)617 IMPL_LINK_NOARG(SfxTemplateManagerDlg, ImportClickHdl, weld::Button&, void)
618 {
619     //Modal Dialog to select Category
620     SfxTemplateCategoryDialog aDlg(m_xDialog.get());
621     aDlg.SetCategoryLBEntries(mxLocalView->getFolderNames());
622 
623     if (aDlg.run() == RET_OK)
624     {
625         const OUString& sCategory = aDlg.GetSelectedCategory();
626         bool bIsNewCategory = aDlg.IsNewCategoryCreated();
627         if(bIsNewCategory)
628         {
629             if(mxLocalView->createRegion(sCategory))
630             {
631                 mxCBFolder->append_text(sCategory);
632                 OnTemplateImportCategory(sCategory);
633             }
634             else
635             {
636                 OUString aMsg( SfxResId(STR_CREATE_ERROR) );
637                 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
638                                                           VclMessageType::Warning, VclButtonsType::Ok,
639                                                           aMsg.replaceFirst("$1", sCategory)));
640                 xBox->run();
641                 return;
642             }
643         }
644         else
645             OnTemplateImportCategory(sCategory);
646     }
647 
648     mxLocalView->reload();
649     mxLocalView->showAllTemplates();
650     if (mxSearchView->IsVisible())
651         SearchUpdate();
652     mxCBApp->set_active(0);
653     mxCBFolder->set_active(0);
654     mxActionBar->set_item_visible(MNI_ACTION_RENAME_FOLDER, false);
655 }
656 
IMPL_STATIC_LINK_NOARG(SfxTemplateManagerDlg,LinkClickHdl,weld::Button &,void)657 IMPL_STATIC_LINK_NOARG(SfxTemplateManagerDlg, LinkClickHdl, weld::Button&, void)
658 {
659     uno::Sequence<beans::PropertyValue> aArgs(1);
660     aArgs[0].Name = "AdditionsTag";
661     aArgs[0].Value <<= OUString("Templates");
662     comphelper::dispatchCommand(".uno:AdditionsDialog", aArgs);
663 }
664 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,OpenRegionHdl,void *,void)665 IMPL_LINK_NOARG(SfxTemplateManagerDlg, OpenRegionHdl, void*, void)
666 {
667     maSelTemplates.clear();
668     mxOKButton->set_sensitive(false);
669     mxActionBar->show();
670 }
671 
IMPL_LINK(SfxTemplateManagerDlg,CreateContextMenuHdl,ThumbnailViewItem *,pItem,void)672 IMPL_LINK(SfxTemplateManagerDlg, CreateContextMenuHdl, ThumbnailViewItem*, pItem, void)
673 {
674     const TemplateViewItem *pViewItem = dynamic_cast<TemplateViewItem*>(pItem);
675 
676     if (pViewItem)
677     {
678         if (mxSearchView->IsVisible())
679             mxSearchView->createContextMenu(pViewItem->IsDefaultTemplate(), TemplateLocalView::IsInternalTemplate(pViewItem->getPath()));
680         else
681             mxLocalView->createContextMenu(pViewItem->IsDefaultTemplate(), TemplateLocalView::IsInternalTemplate(pViewItem->getPath()));
682     }
683 }
684 
IMPL_LINK(SfxTemplateManagerDlg,OpenTemplateHdl,ThumbnailViewItem *,pItem,void)685 IMPL_LINK(SfxTemplateManagerDlg, OpenTemplateHdl, ThumbnailViewItem*, pItem, void)
686 {
687     uno::Sequence< PropertyValue > aArgs(5);
688     aArgs[0].Name = "AsTemplate";
689     aArgs[0].Value <<= true;
690     aArgs[1].Name = "MacroExecutionMode";
691     aArgs[1].Value <<= MacroExecMode::USE_CONFIG;
692     aArgs[2].Name = "UpdateDocMode";
693     aArgs[2].Value <<= UpdateDocMode::ACCORDING_TO_CONFIG;
694     aArgs[3].Name = "InteractionHandler";
695     aArgs[3].Value <<= task::InteractionHandler::createWithParent( ::comphelper::getProcessComponentContext(), nullptr );
696     aArgs[4].Name = "ReadOnly";
697     aArgs[4].Value <<= true;
698 
699     TemplateViewItem *pTemplateItem = static_cast<TemplateViewItem*>(pItem);
700 
701     try
702     {
703         mxDesktop->loadComponentFromURL(pTemplateItem->getPath(),"_default", 0, aArgs );
704     }
705     catch( const uno::Exception& )
706     {
707     }
708 
709     m_xDialog->response(RET_OK);
710 }
711 
IMPL_LINK(SfxTemplateManagerDlg,EditTemplateHdl,ThumbnailViewItem *,pItem,void)712 IMPL_LINK(SfxTemplateManagerDlg, EditTemplateHdl, ThumbnailViewItem*, pItem, void)
713 {
714     uno::Sequence< PropertyValue > aArgs(3);
715     aArgs[0].Name = "AsTemplate";
716     aArgs[0].Value <<= false;
717     aArgs[1].Name = "MacroExecutionMode";
718     aArgs[1].Value <<= MacroExecMode::USE_CONFIG;
719     aArgs[2].Name = "UpdateDocMode";
720     aArgs[2].Value <<= UpdateDocMode::ACCORDING_TO_CONFIG;
721 
722     uno::Reference< XStorable > xStorable;
723     TemplateViewItem *pViewItem = static_cast<TemplateViewItem*>(pItem);
724 
725     try
726     {
727         xStorable.set( mxDesktop->loadComponentFromURL(pViewItem->getPath(),"_default", 0, aArgs ),
728                        uno::UNO_QUERY );
729     }
730     catch( const uno::Exception& )
731     {
732     }
733 
734     m_xDialog->response(RET_OK);
735 }
736 
IMPL_LINK(SfxTemplateManagerDlg,DeleteTemplateHdl,ThumbnailViewItem *,pItem,void)737 IMPL_LINK(SfxTemplateManagerDlg, DeleteTemplateHdl, ThumbnailViewItem*, pItem, void)
738 {
739     OUString aDeletedTemplate;
740     if(mxSearchView->IsVisible())
741     {
742         TemplateSearchViewItem *pSrchItem = static_cast<TemplateSearchViewItem*>(pItem);
743 
744         if (!mxLocalView->removeTemplate(pSrchItem->mnAssocId, pSrchItem->mnRegionId))
745         {
746             aDeletedTemplate = pSrchItem->maTitle;
747         }
748     }
749     else
750     {
751         TemplateViewItem *pViewItem = static_cast<TemplateViewItem*>(pItem);
752         sal_uInt16 nRegionItemId = mxLocalView->getRegionId(pViewItem->mnRegionId);
753 
754         if (!mxLocalView->removeTemplate(pViewItem->mnDocId + 1, nRegionItemId))//mnId w.r.t. region is mnDocId + 1;
755         {
756             aDeletedTemplate = pItem->maTitle;
757         }
758     }
759 
760     if (!aDeletedTemplate.isEmpty())
761     {
762         OUString aMsg( SfxResId(STR_MSG_ERROR_DELETE_TEMPLATE) );
763         std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
764                                                   VclMessageType::Warning, VclButtonsType::Ok,
765                                                   aMsg.replaceFirst("$1",aDeletedTemplate)));
766         xBox->run();
767     }
768 }
769 
IMPL_LINK(SfxTemplateManagerDlg,DefaultTemplateHdl,ThumbnailViewItem *,pItem,void)770 IMPL_LINK(SfxTemplateManagerDlg, DefaultTemplateHdl, ThumbnailViewItem*, pItem, void)
771 {
772     TemplateViewItem *pViewItem = static_cast<TemplateViewItem*>(pItem);
773     OUString aServiceName;
774 
775     if(!pViewItem->IsDefaultTemplate())
776     {
777         if (lcl_getServiceName(pViewItem->getPath(),aServiceName))
778         {
779             OUString sPrevDefault = SfxObjectFactory::GetStandardTemplate( aServiceName );
780             if(!sPrevDefault.isEmpty())
781             {
782                 if(mxSearchView->IsVisible())
783                     mxSearchView->RemoveDefaultTemplateIcon(sPrevDefault);
784                 else
785                     mxLocalView->RemoveDefaultTemplateIcon(sPrevDefault);
786             }
787             SfxObjectFactory::SetStandardTemplate(aServiceName,pViewItem->getPath());
788             pViewItem->showDefaultIcon(true);
789         }
790     }
791     else
792     {
793         if(lcl_getServiceName(pViewItem->getPath(),aServiceName))
794         {
795             SfxObjectFactory::SetStandardTemplate( aServiceName, OUString() );
796             pViewItem->showDefaultIcon(false);
797         }
798     }
799 
800     createDefaultTemplateMenu();
801 }
802 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,SearchUpdateHdl,weld::Entry &,void)803 IMPL_LINK_NOARG(SfxTemplateManagerDlg, SearchUpdateHdl, weld::Entry&, void)
804 {
805     m_aUpdateDataTimer.Start();
806 }
807 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,ImplUpdateDataHdl,Timer *,void)808 IMPL_LINK_NOARG(SfxTemplateManagerDlg, ImplUpdateDataHdl, Timer*, void)
809 {
810     SearchUpdate();
811 }
812 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,LoseFocusHdl,weld::Widget &,void)813 IMPL_LINK_NOARG(SfxTemplateManagerDlg, LoseFocusHdl, weld::Widget&, void)
814 {
815     if (m_aUpdateDataTimer.IsActive())
816     {
817         m_aUpdateDataTimer.Stop();
818         m_aUpdateDataTimer.Invoke();
819     }
820 }
821 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,ListViewHdl,weld::Toggleable &,void)822 IMPL_LINK_NOARG ( SfxTemplateManagerDlg, ListViewHdl, weld::Toggleable&, void )
823 {
824     setTemplateViewMode(TemplateViewMode::eListView);
825 
826     if (mxSearchFilter->get_text().isEmpty())
827         mxLocalView->ListView::grab_focus();
828     else
829         mxSearchView->ListView::grab_focus();
830 }
831 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,ThumbnailViewHdl,weld::Toggleable &,void)832 IMPL_LINK_NOARG ( SfxTemplateManagerDlg, ThumbnailViewHdl, weld::Toggleable&, void )
833 {
834     setTemplateViewMode(TemplateViewMode::eThumbnailView);
835     bMakeSelItemVisible = true;
836 
837     if (mxSearchFilter->get_text().isEmpty())
838         mxLocalView->ThumbnailView::GrabFocus();
839     else
840         mxSearchView->ThumbnailView::GrabFocus();
841 }
842 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,FocusRectLocalHdl,weld::Widget &,tools::Rectangle)843 IMPL_LINK_NOARG(SfxTemplateManagerDlg, FocusRectLocalHdl, weld::Widget&, tools::Rectangle)
844 {
845     if(bMakeSelItemVisible && !maSelTemplates.empty())
846         mxLocalView->MakeItemVisible((*maSelTemplates.begin())->mnId);
847     bMakeSelItemVisible = false;
848     return tools::Rectangle();
849 }
850 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,FocusRectSearchHdl,weld::Widget &,tools::Rectangle)851 IMPL_LINK_NOARG(SfxTemplateManagerDlg, FocusRectSearchHdl, weld::Widget&, tools::Rectangle)
852 {
853     if(bMakeSelItemVisible && !maSelTemplates.empty())
854         mxSearchView->MakeItemVisible((*maSelTemplates.begin())->mnId);
855     bMakeSelItemVisible = false;
856     return tools::Rectangle();
857 }
858 
SearchUpdate()859 void SfxTemplateManagerDlg::SearchUpdate()
860 {
861     OUString aKeyword = mxSearchFilter->get_text();
862 
863     if (!aKeyword.isEmpty())
864     {
865         mxSearchView->Clear();
866 
867         // if the search view is hidden, hide the folder view and display search one
868         if (!mxSearchView->IsVisible())
869         {
870             mxLocalView->deselectItems();
871             mxSearchView->Show();
872             mxLocalView->Hide();
873         }
874 
875         std::vector<TemplateItemProperties> aItems =
876                 mxLocalView->getFilteredItems(SearchView_Keyword(aKeyword, getCurrentApplicationFilter()));
877 
878         for (const TemplateItemProperties& rItem : aItems)
879         {
880             OUString aFolderName = mxLocalView->getRegionName(rItem.nRegionId);
881 
882             mxSearchView->AppendItem(rItem.nId,mxLocalView->getRegionId(rItem.nRegionId),
883                                      rItem.nDocId,
884                                      rItem.aName,
885                                      aFolderName,
886                                      rItem.aPath,
887                                      rItem.aThumbnail);
888         }
889         mxSearchView->sort();
890         mxSearchView->Invalidate();
891     }
892     else
893     {
894         mxSearchView->deselectItems();
895         mxSearchView->Hide();
896         mxLocalView->Show();
897         mxLocalView->filterItems(ViewFilter_Application(getCurrentApplicationFilter()));
898         mxLocalView->reload();
899         if(mxSearchView->IsVisible())
900             SearchUpdate();
901         OUString sLastFolder = mxCBFolder->get_active_text();
902         mxLocalView->showRegion(sLastFolder);
903         mxActionBar->set_item_visible(MNI_ACTION_RENAME_FOLDER, true);
904     }
905 }
906 
IMPL_LINK_NOARG(SfxTemplateManagerDlg,GetFocusHdl,weld::Widget &,void)907 IMPL_LINK_NOARG(SfxTemplateManagerDlg, GetFocusHdl, weld::Widget&, void)
908 {
909     mxLocalView->deselectItems();
910     mxSearchView->deselectItems();
911 
912     maSelTemplates.clear();
913 }
914 
OnTemplateState(const ThumbnailViewItem * pItem)915 void SfxTemplateManagerDlg::OnTemplateState (const ThumbnailViewItem *pItem)
916 {
917     bool bInSelection = maSelTemplates.find(pItem) != maSelTemplates.end();
918 
919     if (pItem->isSelected())
920     {
921         if (maSelTemplates.empty())
922         {
923             mxOKButton->set_sensitive(true);
924         }
925         else if (maSelTemplates.size() != 1 || !bInSelection)
926         {
927             mxOKButton->set_sensitive(false);
928         }
929 
930         if (!bInSelection)
931             maSelTemplates.insert(pItem);
932     }
933     else
934     {
935         if (bInSelection)
936         {
937             maSelTemplates.erase(pItem);
938 
939             if (maSelTemplates.empty())
940             {
941                 mxOKButton->set_sensitive(false);
942             }
943             else if (maSelTemplates.size() == 1)
944             {
945                 mxOKButton->set_sensitive(true);
946             }
947         }
948     }
949 
950     if(maSelTemplates.empty())
951     {
952         mxMoveButton->set_sensitive(false);
953         mxExportButton->set_sensitive(false);
954     }
955     else
956     {
957         mxMoveButton->set_sensitive(true);
958         mxExportButton->set_sensitive(true);
959     }
960 }
961 
OnTemplateImportCategory(std::u16string_view sCategory)962 void SfxTemplateManagerDlg::OnTemplateImportCategory(std::u16string_view sCategory)
963 {
964     sfx2::FileDialogHelper aFileDlg(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
965                                     FileDialogFlags::MultiSelection, m_xDialog.get());
966 
967     // add "All" filter
968     aFileDlg.AddFilter( SfxResId(STR_SFX_FILTERNAME_ALL),
969                         FILEDIALOG_FILTER_ALL );
970 
971     // add template filter
972     OUString sFilterExt;
973     OUString sFilterName( SfxResId( STR_TEMPLATE_FILTER ) );
974 
975     // add filters of modules which are installed
976     SvtModuleOptions aModuleOpt;
977     if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) )
978         sFilterExt += "*.ott;*.stw;*.oth;*.dotx;*.dot";
979 
980     if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) )
981     {
982         if ( !sFilterExt.isEmpty() )
983             sFilterExt += ";";
984 
985         sFilterExt += "*.ots;*.stc;*.xltx;*.xlt";
986     }
987 
988     if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) )
989     {
990         if ( !sFilterExt.isEmpty() )
991             sFilterExt += ";";
992 
993         sFilterExt += "*.otp;*.sti;*.pot;*.potx";
994     }
995 
996     if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::DRAW ) )
997     {
998         if ( !sFilterExt.isEmpty() )
999             sFilterExt += ";";
1000 
1001         sFilterExt += "*.otg;*.std";
1002     }
1003 
1004     if ( !sFilterExt.isEmpty() )
1005         sFilterExt += ";";
1006 
1007     sFilterExt += "*.vor";
1008 
1009     sFilterName += " (" + sFilterExt + ")";
1010 
1011     aFileDlg.AddFilter( sFilterName, sFilterExt );
1012     aFileDlg.SetCurrentFilter( sFilterName );
1013 
1014     ErrCode nCode = aFileDlg.Execute();
1015 
1016     if ( nCode != ERRCODE_NONE )
1017         return;
1018 
1019     const css::uno::Sequence<OUString> aFiles = aFileDlg.GetSelectedFiles();
1020 
1021     if (!aFiles.hasElements())
1022         return;
1023 
1024     //Import to the selected regions
1025     TemplateContainerItem* pContItem = mxLocalView->getRegion(sCategory);
1026     if(!pContItem)
1027         return;
1028 
1029     OUString aTemplateList;
1030 
1031     for (const auto& rFile : aFiles)
1032     {
1033         if(!mxLocalView->copyFrom(pContItem, rFile))
1034         {
1035             if (aTemplateList.isEmpty())
1036                 aTemplateList = rFile;
1037             else
1038                 aTemplateList += "\n" + rFile;
1039         }
1040     }
1041 
1042     if (!aTemplateList.isEmpty())
1043     {
1044         OUString aMsg(SfxResId(STR_MSG_ERROR_IMPORT));
1045         aMsg = aMsg.replaceFirst("$1",pContItem->maTitle);
1046         std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
1047                                                   VclMessageType::Warning, VclButtonsType::Ok,
1048                                                   aMsg.replaceFirst("$2",aTemplateList)));
1049         xBox->run();
1050     }
1051 }
1052 
OnTemplateExport()1053 void SfxTemplateManagerDlg::OnTemplateExport()
1054 {
1055     uno::Reference<XComponentContext> xContext(comphelper::getProcessComponentContext());
1056     uno::Reference<XFolderPicker2> xFolderPicker = FolderPicker::create(xContext);
1057 
1058     xFolderPicker->setDisplayDirectory(SvtPathOptions().GetWorkPath());
1059 
1060     sal_Int16 nResult = xFolderPicker->execute();
1061     sal_Int16 nCount = maSelTemplates.size();
1062 
1063     if( nResult != ExecutableDialogResults::OK )
1064         return;
1065 
1066     OUString aTemplateList;
1067     INetURLObject aPathObj(xFolderPicker->getDirectory());
1068     aPathObj.setFinalSlash();
1069 
1070     if (mxSearchView->IsVisible())
1071     {
1072         sal_uInt16 i = 1;
1073 
1074         for (auto const& selTemplate : maSelTemplates)
1075         {
1076             const TemplateSearchViewItem *pItem = static_cast<const TemplateSearchViewItem*>(selTemplate);
1077 
1078             INetURLObject aItemPath(pItem->getPath());
1079 
1080             if ( 1 == i )
1081                 aPathObj.Append(aItemPath.getName());
1082             else
1083                 aPathObj.setName(aItemPath.getName());
1084 
1085             OUString aPath = aPathObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1086 
1087             if (!mxLocalView->exportTo(pItem->mnAssocId,pItem->mnRegionId,aPath))
1088             {
1089                 if (aTemplateList.isEmpty())
1090                     aTemplateList = pItem->maTitle;
1091                 else
1092                     aTemplateList += "\n" + pItem->maTitle;
1093             }
1094             ++i;
1095         }
1096 
1097         mxSearchView->deselectItems();
1098     }
1099     else
1100     {
1101         // export templates from the current view
1102 
1103         sal_uInt16 i = 1;
1104 
1105         for (auto const& selTemplate : maSelTemplates)
1106         {
1107             const TemplateViewItem *pItem = static_cast<const TemplateViewItem*>(selTemplate);
1108 
1109             INetURLObject aItemPath(pItem->getPath());
1110 
1111             if ( 1 == i )
1112                 aPathObj.Append(aItemPath.getName());
1113             else
1114                 aPathObj.setName(aItemPath.getName());
1115 
1116             OUString aPath = aPathObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1117 
1118             if (!mxLocalView->exportTo(pItem->mnDocId + 1,   //mnId w.r.t. region = mDocId + 1
1119                 mxLocalView->getRegionId(pItem->mnRegionId), //pItem->mnRegionId does not store actual region Id
1120                 aPath))
1121             {
1122                 if (aTemplateList.isEmpty())
1123                     aTemplateList = pItem->maTitle;
1124                 else
1125                     aTemplateList += "\n" + pItem->maTitle;
1126             }
1127             ++i;
1128         }
1129 
1130         mxLocalView->deselectItems();
1131     }
1132 
1133     if (!aTemplateList.isEmpty())
1134     {
1135         OUString aText( SfxResId(STR_MSG_ERROR_EXPORT) );
1136         std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
1137                                                   VclMessageType::Warning, VclButtonsType::Ok,
1138                                                   aText.replaceFirst("$1",aTemplateList)));
1139         xBox->run();
1140     }
1141     else
1142     {
1143         OUString sText( SfxResId(STR_MSG_EXPORT_SUCCESS) );
1144         std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
1145                                                   VclMessageType::Info, VclButtonsType::Ok,
1146                                                   sText.replaceFirst("$1", OUString::number(nCount))));
1147         xBox->run();
1148     }
1149 }
1150 
OnTemplateOpen()1151 void SfxTemplateManagerDlg::OnTemplateOpen ()
1152 {
1153     ThumbnailViewItem *pItem = const_cast<ThumbnailViewItem*>(*maSelTemplates.begin());
1154 
1155     OpenTemplateHdl(pItem);
1156 }
1157 
OnCategoryNew()1158 void SfxTemplateManagerDlg::OnCategoryNew()
1159 {
1160     InputDialog dlg(m_xDialog.get(), SfxResId(STR_INPUT_NEW));
1161 
1162     int ret = dlg.run();
1163 
1164     if (!ret)
1165         return;
1166 
1167     OUString aName = dlg.GetEntryText();
1168 
1169     if(mxLocalView->createRegion(aName))
1170         mxCBFolder->append_text(aName);
1171     else
1172     {
1173         OUString aMsg( SfxResId(STR_CREATE_ERROR) );
1174         std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
1175                                                   VclMessageType::Warning, VclButtonsType::Ok,
1176                                                   aMsg.replaceFirst("$1", aName)));
1177         xBox->run();
1178     }
1179 }
1180 
OnCategoryRename()1181 void SfxTemplateManagerDlg::OnCategoryRename()
1182 {
1183     OUString sCategory = mxCBFolder->get_active_text();
1184     InputDialog dlg(m_xDialog.get(), SfxResId(STR_INPUT_NEW));
1185 
1186     dlg.SetEntryText(sCategory);
1187     int ret = dlg.run();
1188 
1189     if (!ret)
1190         return;
1191 
1192     OUString aName = dlg.GetEntryText();
1193 
1194     if(mxLocalView->renameRegion(sCategory, aName))
1195     {
1196         sal_Int32 nPos = mxCBFolder->find_text(sCategory);
1197         mxCBFolder->remove(nPos);
1198         mxCBFolder->insert_text(nPos, aName);
1199         mxCBFolder->set_active(nPos);
1200 
1201         mxLocalView->reload();
1202         mxLocalView->showRegion(aName);
1203     }
1204     else
1205     {
1206         OUString aMsg( SfxResId(STR_CREATE_ERROR) );
1207         std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
1208                                                   VclMessageType::Warning, VclButtonsType::Ok,
1209                                                   aMsg.replaceFirst("$1", aName)));
1210         xBox->run();
1211     }
1212 }
1213 
OnCategoryDelete()1214 void SfxTemplateManagerDlg::OnCategoryDelete()
1215 {
1216     SfxTemplateCategoryDialog aDlg(m_xDialog.get());
1217     aDlg.SetCategoryLBEntries(mxLocalView->getFolderNames());
1218     aDlg.HideNewCategoryOption();
1219     aDlg.set_title(MnemonicGenerator::EraseAllMnemonicChars(SfxResId(STR_CATEGORY_DELETE)));
1220     aDlg.SetSelectLabelText(SfxResId(STR_CATEGORY_SELECT));
1221 
1222     if (aDlg.run() == RET_OK)
1223     {
1224         const OUString& sCategory = aDlg.GetSelectedCategory();
1225         std::unique_ptr<weld::MessageDialog> popupDlg(Application::CreateMessageDialog(m_xDialog.get(),
1226                                                       VclMessageType::Question, VclButtonsType::YesNo,
1227                                                       SfxResId(STR_QMSG_SEL_FOLDER_DELETE)));
1228         if (popupDlg->run() != RET_YES)
1229             return;
1230 
1231         sal_Int16 nItemId = mxLocalView->getRegionId(sCategory);
1232 
1233         if (!mxLocalView->removeRegion(nItemId))
1234         {
1235             OUString sMsg( SfxResId(STR_MSG_ERROR_DELETE_FOLDER) );
1236             std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
1237                                                       VclMessageType::Warning, VclButtonsType::Ok,
1238                                                       sMsg.replaceFirst("$1",sCategory)));
1239             xBox->run();
1240         }
1241         else
1242         {
1243             mxCBFolder->remove_text(sCategory);
1244         }
1245     }
1246 
1247     mxLocalView->reload();
1248     mxLocalView->showAllTemplates();
1249     mxCBApp->set_active(0);
1250     mxCBFolder->set_active(0);
1251     mxActionBar->set_item_visible(MNI_ACTION_RENAME_FOLDER, false);
1252 }
1253 
createDefaultTemplateMenu()1254 void SfxTemplateManagerDlg::createDefaultTemplateMenu ()
1255 {
1256     std::vector<OUString> aList = lcl_getAllFactoryURLs();
1257 
1258     if (!aList.empty())
1259     {
1260         mxTemplateDefaultMenu->clear();
1261 
1262         for (auto const& elem : aList)
1263         {
1264             INetURLObject aObj(elem);
1265             OUString aTitle = SvFileInformationManager::GetDescription(aObj);
1266             mxTemplateDefaultMenu->append(elem, aTitle, SvFileInformationManager::GetImageId(aObj));
1267         }
1268 
1269         mxActionBar->set_item_visible(MNI_ACTION_DEFAULT, true);
1270     }
1271     else
1272         mxActionBar->set_item_visible(MNI_ACTION_DEFAULT, false);
1273 }
1274 
localMoveTo(sal_uInt16 nItemId)1275 void SfxTemplateManagerDlg::localMoveTo(sal_uInt16 nItemId)
1276 {
1277     if (nItemId)
1278     {
1279         // Move templates to desired folder if for some reason move fails
1280         // try copying them.
1281         mxLocalView->moveTemplates(maSelTemplates,nItemId);
1282     }
1283 }
1284 
localSearchMoveTo(sal_uInt16 nItemId)1285 void SfxTemplateManagerDlg::localSearchMoveTo(sal_uInt16 nItemId)
1286 {
1287     if (nItemId)
1288     {
1289         // Move templates to desired folder if for some reason move fails
1290         // try copying them.
1291         std::set<const ThumbnailViewItem*,selection_cmp_fn> aSelTemplates = maSelTemplates; //Copy to avoid invalidating an iterator
1292 
1293         for (auto const& selTemplate : aSelTemplates)
1294         {
1295             const TemplateSearchViewItem *pItem =
1296                     static_cast<const TemplateSearchViewItem*>(selTemplate);
1297 
1298             if(!mxLocalView->moveTemplate(pItem,pItem->mnRegionId,nItemId))
1299             {
1300                 OUString sDst = mxLocalView->getRegionItemName(nItemId);
1301                 OUString sMsg(SfxResId(STR_MSG_ERROR_LOCAL_MOVE));
1302                 sMsg = sMsg.replaceFirst("$1",sDst);
1303                 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
1304                                                           VclMessageType::Warning, VclButtonsType::Ok,
1305                                                           sMsg.replaceFirst( "$2",pItem->maTitle)));
1306                 xBox->run();
1307             }
1308         }
1309     }
1310 
1311     // Deselect all items and update search results
1312     mxSearchView->deselectItems();
1313 
1314     SearchUpdateHdl(*mxSearchFilter);
1315 }
1316 
lcl_getServiceName(const OUString & rFileURL,OUString & rName)1317 static bool lcl_getServiceName ( const OUString &rFileURL, OUString &rName )
1318 {
1319     bool bRet = false;
1320 
1321     if ( !rFileURL.isEmpty() )
1322     {
1323         try
1324         {
1325             uno::Reference< embed::XStorage > xStorage =
1326                     comphelper::OStorageHelper::GetStorageFromURL( rFileURL, embed::ElementModes::READ );
1327 
1328             SotClipboardFormatId nFormat = SotStorage::GetFormatID( xStorage );
1329 
1330             std::shared_ptr<const SfxFilter> pFilter = SfxGetpApp()->GetFilterMatcher().GetFilter4ClipBoardId( nFormat );
1331 
1332             if ( pFilter )
1333             {
1334                 rName = pFilter->GetServiceName();
1335                 bRet = true;
1336             }
1337         }
1338         catch( uno::Exception& )
1339         {}
1340     }
1341 
1342     return bRet;
1343 }
1344 
lcl_getAllFactoryURLs()1345 static std::vector<OUString> lcl_getAllFactoryURLs ()
1346 {
1347     SvtModuleOptions aModOpt;
1348     std::vector<OUString> aList;
1349     const css::uno::Sequence<OUString> &aServiceNames = aModOpt.GetAllServiceNames();
1350 
1351     for( const auto& rServiceName : aServiceNames )
1352     {
1353         if ( ! SfxObjectFactory::GetStandardTemplate( rServiceName ).isEmpty() )
1354         {
1355             SvtModuleOptions::EFactory eFac = SvtModuleOptions::EFactory::WRITER;
1356             SvtModuleOptions::ClassifyFactoryByName( rServiceName, eFac );
1357             aList.push_back(aModOpt.GetFactoryEmptyDocumentURL(eFac));
1358         }
1359     }
1360 
1361     return aList;
1362 }
1363 
1364 
1365 //   Class SfxTemplateCategoryDialog --------------------------------------------------
1366 
SfxTemplateCategoryDialog(weld::Window * pParent)1367 SfxTemplateCategoryDialog::SfxTemplateCategoryDialog(weld::Window* pParent)
1368     : GenericDialogController(pParent, "sfx/ui/templatecategorydlg.ui", "TemplatesCategoryDialog")
1369     , msSelectedCategory(OUString())
1370     , mbIsNewCategory(false)
1371     , mxLBCategory(m_xBuilder->weld_tree_view("categorylb"))
1372     , mxSelectLabel(m_xBuilder->weld_label("select_label"))
1373     , mxNewCategoryEdit(m_xBuilder->weld_entry("category_entry"))
1374     , mxCreateLabel(m_xBuilder->weld_label("create_label"))
1375     , mxOKButton(m_xBuilder->weld_button("ok"))
1376 {
1377     mxLBCategory->append_text(SfxResId(STR_CATEGORY_NONE));
1378     mxNewCategoryEdit->connect_changed(LINK(this, SfxTemplateCategoryDialog, NewCategoryEditHdl));
1379     mxLBCategory->set_size_request(mxLBCategory->get_approximate_digit_width() * 32,
1380                                    mxLBCategory->get_height_rows(8));
1381     mxLBCategory->connect_changed(LINK(this, SfxTemplateCategoryDialog, SelectCategoryHdl));
1382     mxOKButton->set_sensitive(false);
1383 }
1384 
~SfxTemplateCategoryDialog()1385 SfxTemplateCategoryDialog::~SfxTemplateCategoryDialog()
1386 {
1387 }
1388 
IMPL_LINK_NOARG(SfxTemplateCategoryDialog,NewCategoryEditHdl,weld::Entry &,void)1389 IMPL_LINK_NOARG(SfxTemplateCategoryDialog, NewCategoryEditHdl, weld::Entry&, void)
1390 {
1391     OUString sParam = comphelper::string::strip(mxNewCategoryEdit->get_text(), ' ');
1392     mxLBCategory->set_sensitive(sParam.isEmpty());
1393     if(!sParam.isEmpty())
1394     {
1395         msSelectedCategory = sParam;
1396         mbIsNewCategory = true;
1397         mxOKButton->set_sensitive(true);
1398     }
1399     else
1400     {
1401         SelectCategoryHdl(*mxLBCategory);
1402         mbIsNewCategory = false;
1403     }
1404 }
1405 
IMPL_LINK_NOARG(SfxTemplateCategoryDialog,SelectCategoryHdl,weld::TreeView &,void)1406 IMPL_LINK_NOARG(SfxTemplateCategoryDialog, SelectCategoryHdl, weld::TreeView&, void)
1407 {
1408     if (mxLBCategory->get_selected_index() == 0)
1409     {
1410         msSelectedCategory = OUString();
1411         mxOKButton->set_sensitive(false);
1412         mxNewCategoryEdit->set_sensitive(true);
1413     }
1414     else
1415     {
1416         msSelectedCategory = mxLBCategory->get_selected_text();
1417         mxNewCategoryEdit->set_sensitive(false);
1418         mxOKButton->set_sensitive(true);
1419     }
1420 
1421     mbIsNewCategory = false;
1422 }
1423 
SetCategoryLBEntries(std::vector<OUString> aFolderNames)1424 void SfxTemplateCategoryDialog::SetCategoryLBEntries(std::vector<OUString> aFolderNames)
1425 {
1426     for (size_t i = 0, n = aFolderNames.size(); i < n; ++i)
1427         mxLBCategory->append_text(aFolderNames[i]);
1428     mxLBCategory->select(0);
1429 }
1430 
HideNewCategoryOption()1431 void SfxTemplateCategoryDialog::HideNewCategoryOption()
1432 {
1433     mxCreateLabel->hide();
1434     mxNewCategoryEdit->hide();
1435 }
1436 
1437 // SfxTemplateSelectionDialog -----------------------------------------------------------------
1438 
SfxTemplateSelectionDlg(weld::Window * pParent)1439 SfxTemplateSelectionDlg::SfxTemplateSelectionDlg(weld::Window* pParent)
1440     : SfxTemplateManagerDlg(pParent)
1441     , msTemplatePath(OUString())
1442 {
1443     mxCBApp->set_active(MNI_IMPRESS);
1444     mxCBFolder->set_active(0);
1445     m_xDialog->set_title(SfxResId(STR_TEMPLATE_SELECTION));
1446 
1447     if (mxLocalView->IsVisible())
1448     {
1449         mxLocalView->filterItems(ViewFilter_Application(getCurrentApplicationFilter()));
1450         mxLocalView->showAllTemplates();
1451     }
1452 
1453     mxCBApp->set_sensitive(false);
1454     mxActionBar->hide();
1455     mxMoveButton->hide();
1456     mxExportButton->hide();
1457     mxCBXHideDlg->show();
1458     mxCBXHideDlg->set_active(true);
1459 
1460     mxLocalView->setOpenTemplateHdl(LINK(this,SfxTemplateSelectionDlg, OpenTemplateHdl));
1461     mxSearchView->setOpenTemplateHdl(LINK(this,SfxTemplateSelectionDlg, OpenTemplateHdl));
1462 
1463     mxSearchView->SetMultiSelectionEnabled(false);
1464 
1465     mxOKButton->connect_clicked(LINK(this, SfxTemplateSelectionDlg, OkClickHdl));
1466 }
1467 
~SfxTemplateSelectionDlg()1468 SfxTemplateSelectionDlg::~SfxTemplateSelectionDlg()
1469 {
1470     maIdle.Stop();
1471 }
1472 
run()1473 short SfxTemplateSelectionDlg::run()
1474 {
1475     // tdf#124597 at startup this dialog is launched before its parent window
1476     // has taken its final size. The parent size request is processed during
1477     // the dialogs event loop so configure this dialog to center to
1478     // the parents pending geometry request
1479     m_xDialog->set_centered_on_parent(true);
1480 
1481     // tdf#125079 toggle off the size tracking at some future idle point
1482     maIdle.SetPriority(TaskPriority::LOWEST);
1483     maIdle.SetDebugName("sfx2 SfxTemplateManagerDlg maIdle");
1484     maIdle.SetInvokeHandler(LINK(this,SfxTemplateSelectionDlg,TimeOut));
1485     maIdle.Start();
1486     setTemplateViewMode(TemplateViewMode::eThumbnailView);
1487 
1488     return weld::GenericDialogController::run();
1489 }
1490 
IMPL_LINK_NOARG(SfxTemplateSelectionDlg,TimeOut,Timer *,void)1491 IMPL_LINK_NOARG(SfxTemplateSelectionDlg, TimeOut, Timer*, void)
1492 {
1493     m_xDialog->set_centered_on_parent(false);
1494 }
1495 
IMPL_LINK(SfxTemplateSelectionDlg,OpenTemplateHdl,ThumbnailViewItem *,pItem,void)1496 IMPL_LINK(SfxTemplateSelectionDlg, OpenTemplateHdl, ThumbnailViewItem*, pItem, void)
1497 {
1498     TemplateViewItem *pViewItem = static_cast<TemplateViewItem*>(pItem);
1499     msTemplatePath = pViewItem->getPath();
1500 
1501     m_xDialog->response(RET_OK);
1502 }
1503 
IMPL_LINK_NOARG(SfxTemplateSelectionDlg,OkClickHdl,weld::Button &,void)1504 IMPL_LINK_NOARG(SfxTemplateSelectionDlg, OkClickHdl, weld::Button&, void)
1505 {
1506    TemplateViewItem *pViewItem = static_cast<TemplateViewItem*>(const_cast<ThumbnailViewItem*>(*maSelTemplates.begin()));
1507    msTemplatePath = pViewItem->getPath();
1508 
1509    m_xDialog->response(RET_OK);
1510 }
1511 
1512 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1513