LibreOffice Module sfx2 (master) 1
templatelocalview.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
11
12#include <comphelper/string.hxx>
13#include <sfx2/doctempl.hxx>
14#include <sfx2/inputdlg.hxx>
15#include <sfx2/sfxresid.hxx>
17#include <templateviewitem.hxx>
18#include <sfx2/docfac.hxx>
19#include <tools/urlobj.hxx>
21#include <vcl/svapp.hxx>
22#include <vcl/weld.hxx>
23#include <vcl/commandevent.hxx>
24#include <vcl/event.hxx>
25
26#include <sfx2/strings.hrc>
27#include <bitmaps.hlst>
28
30#include <com/sun/star/util/thePathSettings.hpp>
32#include <sfxurlrelocator.hxx>
33#include <../doc/doctemplateslocal.hxx>
34
35using namespace ::com::sun::star;
36
38{
39 bool bRet = rExt == u"ott" || rExt == u"stw" || rExt == u"oth" || rExt == u"dot" || rExt == u"dotx" || rExt == u"otm"
40 || rExt == u"ots" || rExt == u"stc" || rExt == u"xlt" || rExt == u"xltm" || rExt == u"xltx"
41 || rExt == u"otp" || rExt == u"sti" || rExt == u"pot" || rExt == u"potm" || rExt == u"potx"
42 || rExt == u"otg" || rExt == u"std";
43
45 {
46 bRet = rExt == u"ott" || rExt == u"stw" || rExt == u"oth" || rExt == u"dot" || rExt == u"dotx" || rExt == u"otm";
47 }
49 {
50 bRet = rExt == u"ots" || rExt == u"stc" || rExt == u"xlt" || rExt == u"xltm" || rExt == u"xltx";
51 }
53 {
54 bRet = rExt == u"otp" || rExt == u"sti" || rExt == u"pot" || rExt == u"potm" || rExt == u"potx";
55 }
57 {
58 bRet = rExt == u"otg" || rExt == u"std";
59 }
60
61 return bRet;
62}
63
64bool ViewFilter_Application::isValid (std::u16string_view rPath) const
65{
66 INetURLObject aUrl(rPath);
68}
69
71{
72 const TemplateViewItem *pTempItem = dynamic_cast<const TemplateViewItem*>(pItem);
73 if (pTempItem)
74 return isValid(pTempItem->getPath());
75
76 return true;
77}
78
80{
81 mnThumbnailWidth = itemMaxSize;
82 mnThumbnailHeight = itemMaxSize;
83}
84
85TemplateLocalView::TemplateLocalView(std::unique_ptr<weld::ScrolledWindow> xWindow,
86 std::unique_ptr<weld::Menu> xMenu)
87 : ThumbnailView(std::move(xWindow), std::move(xMenu))
88 , mnCurRegionId(0)
89 , maSelectedItem(nullptr)
90 , mnThumbnailWidth(TEMPLATE_THUMBNAIL_MAX_WIDTH)
91 , mnThumbnailHeight(TEMPLATE_THUMBNAIL_MAX_HEIGHT)
92 , maPosition(0,0)
93 , mpDocTemplates(new SfxDocumentTemplates)
94{
95}
96
98{
99}
100
102{
103 maRegions.clear();
104 maAllTemplates.clear();
105
106 sal_uInt16 nCount = mpDocTemplates->GetRegionCount();
107 for (sal_uInt16 i = 0; i < nCount; ++i)
108 {
109 OUString aRegionName(mpDocTemplates->GetFullRegionName(i));
110
111 std::unique_ptr<TemplateContainerItem> pItem(new TemplateContainerItem( i+1 ));
112 pItem->mnRegionId = i;
113 pItem->maTitle = aRegionName;
114
115 sal_uInt16 nEntries = mpDocTemplates->GetCount(i);
116
117 for (sal_uInt16 j = 0; j < nEntries; ++j)
118 {
119 OUString aName = mpDocTemplates->GetName(i,j);
120 OUString aURL = mpDocTemplates->GetPath(i,j);
121
123 aProperties.nId = j+1;
124 aProperties.nDocId = j;
125 aProperties.nRegionId = i;
126 aProperties.aName = aName;
127 aProperties.aPath = aURL;
128 aProperties.aRegionName = aRegionName;
132
133 pItem->maTemplates.push_back(aProperties);
134 maAllTemplates.push_back(aProperties);
135 }
136
137 maRegions.push_back(std::move(pItem));
138 }
139}
140
142{
143 mpDocTemplates->Update();
144 OUString sCurRegionName = getRegionItemName(mnCurRegionId);
145 Populate();
146 mnCurRegionId = getRegionId(sCurRegionName);
147
148 // Check if we are currently browsing a region or root folder
149 if (mnCurRegionId)
150 {
151 sal_uInt16 nRegionId = mnCurRegionId - 1; //Is offset by 1
152
153 for (auto const & pRegion : maRegions)
154 {
155 if (pRegion->mnRegionId == nRegionId)
156 {
157 showRegion(pRegion.get());
158 break;
159 }
160 }
161 }
162 else
164
165 //No items should be selected by default
167}
168
170{
171 mnCurRegionId = 0;
172
173 insertItems(maAllTemplates, false, true);
174
175 maOpenRegionHdl.Call(nullptr);
176}
177
179{
180 mnCurRegionId = pItem->mnRegionId+1;
181
182 insertItems(pItem->maTemplates);
183
184 maOpenRegionHdl.Call(nullptr);
185}
186
188{
189 for (auto const & pRegion : maRegions)
190 if (pRegion->maTitle == rName)
191 return pRegion.get();
192
193 return nullptr;
194}
195
196void TemplateLocalView::ContextMenuSelectHdl(std::u16string_view rIdent)
197{
198 if (rIdent == u"open")
200 else if (rIdent == u"edit")
202 else if (rIdent == u"rename")
203 {
204 InputDialog aTitleEditDlg(GetDrawingArea(), SfxResId(STR_RENAME_TEMPLATE));
205 OUString sOldTitle = maSelectedItem->getTitle();
206 aTitleEditDlg.SetEntryText(sOldTitle);
207 aTitleEditDlg.HideHelpBtn();
208
209 auto aCurRegionItems = getFilteredItems([&](const TemplateItemProperties& rItem) {
211 });
212 OUString sTooltip(SfxResId(STR_TOOLTIP_ERROR_RENAME_TEMPLATE));
213 sTooltip = sTooltip.replaceFirst("$2", getRegionName(maSelectedItem->mnRegionId));
214 aTitleEditDlg.setCheckEntry([&](OUString sNewTitle) {
215 if (sNewTitle.isEmpty() || sNewTitle == sOldTitle)
216 return true;
217 for (const auto& rItem : aCurRegionItems)
218 {
219 if (rItem.aName == sNewTitle)
220 {
221 aTitleEditDlg.SetTooltip(sTooltip.replaceFirst("$1", sNewTitle));
222 return false;
223 }
224 }
225 return true;
226 });
227 if (!aTitleEditDlg.run())
228 return;
229 OUString sNewTitle = comphelper::string::strip(aTitleEditDlg.GetEntryText(), ' ');
230
231 if ( !sNewTitle.isEmpty() && sNewTitle != sOldTitle )
232 {
233 maSelectedItem->setTitle(sNewTitle);
234 }
235 }
236 else if (rIdent == u"delete")
237 {
238 std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo,
239 SfxResId(STR_QMSG_SEL_TEMPLATE_DELETE)));
240 if (xQueryDlg->run() != RET_YES)
241 return;
242
244 reload();
245 }
246 else if (rIdent == u"default")
248}
249
250sal_uInt16 TemplateLocalView::getRegionId(size_t pos) const
251{
252 assert(pos < maRegions.size());
253
254 return maRegions[pos]->mnId;
255}
256
257sal_uInt16 TemplateLocalView::getRegionId(std::u16string_view sRegion) const
258{
259 for (auto const & pRegion : maRegions)
260 {
261 if (pRegion->maTitle == sRegion)
262 return pRegion->mnId;
263 }
264
265 return 0;
266}
267
268OUString TemplateLocalView::getRegionName(const sal_uInt16 nRegionId) const
269{
270 return mpDocTemplates->GetRegionName(nRegionId);
271}
272
273OUString TemplateLocalView::getRegionItemName(const sal_uInt16 nItemId) const
274{
275 for (auto const & pRegion : maRegions)
276 {
277 if (pRegion->mnId == nItemId)
278 return pRegion->maTitle;
279 }
280
281 return OUString();
282}
283
285{
286 size_t n = maRegions.size();
287 std::vector<OUString> ret(n);
288
289 for (size_t i = 0; i < n; ++i)
290 ret[i] = maRegions[i]->maTitle;
291
292 return ret;
293}
294
295std::vector<TemplateItemProperties>
296TemplateLocalView::getFilteredItems(const std::function<bool (const TemplateItemProperties&)> &rFunc) const
297{
298 std::vector<TemplateItemProperties> aItems;
299
300 if (mnCurRegionId)
301 {
302 TemplateContainerItem *pFolderItem = maRegions[mnCurRegionId-1].get();
303
304 for (const TemplateItemProperties & rItemProps : pFolderItem->maTemplates)
305 {
306 if (rFunc(rItemProps))
307 aItems.push_back(rItemProps);
308 }
309 }
310 else
311 {
312 for (auto const & pFolderItem : maRegions)
313 {
314 for (const TemplateItemProperties & rItemProps : pFolderItem->maTemplates)
315 {
316 if (rFunc(rItemProps))
317 aItems.push_back(rItemProps);
318 }
319 }
320 }
321
322 return aItems;
323}
324
325sal_uInt16 TemplateLocalView::createRegion(const OUString &rName)
326{
327 sal_uInt16 nRegionId = mpDocTemplates->GetRegionCount(); // Next regionId
328 sal_uInt16 nItemId = maRegions.size() + 1;
329
330 if (!mpDocTemplates->InsertDir(rName,nRegionId))
331 return 0;
332
333 // Insert to the region cache list and to the thumbnail item list
334 std::unique_ptr<TemplateContainerItem> pItem(new TemplateContainerItem( nItemId ));
335 pItem->mnRegionId = nRegionId;
336 pItem->maTitle = rName;
337
338 maRegions.push_back(std::move(pItem));
339
340 return nItemId;
341}
342
343bool TemplateLocalView::renameRegion(std::u16string_view rTitle, const OUString &rNewTitle)
344{
345 TemplateContainerItem *pRegion = getRegion(rTitle);
346
347 if(pRegion)
348 {
349 sal_uInt16 nRegionId = pRegion->mnRegionId;
350 return mpDocTemplates->SetName( rNewTitle, nRegionId, USHRT_MAX/*nDocId*/ );
351 }
352 return false;
353}
354
355bool TemplateLocalView::removeRegion(const sal_uInt16 nItemId)
356{
357 sal_uInt16 nRegionId = USHRT_MAX;
358
359 // Remove from the region cache list
360 for (auto pRegionIt = maRegions.begin(); pRegionIt != maRegions.end();)
361 {
362 if ( (*pRegionIt)->mnId == nItemId )
363 {
364 if (!mpDocTemplates->Delete((*pRegionIt)->mnRegionId,USHRT_MAX))
365 return false;
366
367 nRegionId = (*pRegionIt)->mnRegionId;
368
369 pRegionIt = maRegions.erase(pRegionIt);
370 }
371 else
372 {
373 // Synchronize regions cache ids with SfxDocumentTemplates
374 if (nRegionId != USHRT_MAX && (*pRegionIt)->mnRegionId > nRegionId)
375 --(*pRegionIt)->mnRegionId;
376
377 ++pRegionIt;
378 }
379 }
380
381 if (nRegionId == USHRT_MAX)
382 return false;
383
384 // Synchronize view regions ids with SfxDocumentTemplates
385 for (auto const& region : maRegions)
386 {
387 if (region->mnRegionId > nRegionId)
388 --region->mnRegionId;
389 }
390
391 return true;
392}
393
394bool TemplateLocalView::removeTemplate (const sal_uInt16 nItemId, const sal_uInt16 nSrcItemId)
395{
396 for (auto const & pRegion : maRegions)
397 {
398 if (pRegion->mnId == nSrcItemId)
399 {
400 TemplateContainerItem *pItem = pRegion.get();
401 auto pIter = std::find_if(pItem->maTemplates.begin(), pItem->maTemplates.end(),
402 [nItemId](const TemplateItemProperties& rTemplate) { return rTemplate.nId == nItemId; });
403 if (pIter != pItem->maTemplates.end())
404 {
405 if (!mpDocTemplates->Delete(pItem->mnRegionId,pIter->nDocId))
406 return false;
407
408 pIter = pItem->maTemplates.erase(pIter);
409
410 if (pRegion->mnRegionId == mnCurRegionId-1)
411 {
412 RemoveItem(nItemId);
413 Invalidate();
414 }
415
416 // Update Doc Idx for all templates that follow
417 for (; pIter != pItem->maTemplates.end(); ++pIter)
418 pIter->nDocId = pIter->nDocId - 1;
419 }
420
422 break;
423 }
424 }
425
426 return true;
427}
428
429void TemplateLocalView::moveTemplates(const std::set<const ThumbnailViewItem*, selection_cmp_fn> &rItems,
430 const sal_uInt16 nTargetItem)
431{
432 TemplateContainerItem *pTarget = nullptr;
433 TemplateContainerItem *pSrc = nullptr;
434
435 for (auto const & pRegion : maRegions)
436 {
437 if (pRegion->mnId == nTargetItem)
438 pTarget = pRegion.get();
439 }
440
441 if (!pTarget)
442 return;
443
444 bool refresh = false;
445
446 sal_uInt16 nTargetRegion = pTarget->mnRegionId;
447 sal_uInt16 nTargetIdx = mpDocTemplates->GetCount(nTargetRegion); // Next Idx
448 std::vector<sal_uInt16> aItemIds; // List of moved items ids (also prevents the invalidation of rItems iterators when we remove them as we go)
449
450 std::set<const ThumbnailViewItem*,selection_cmp_fn>::const_iterator aSelIter;
451 for ( aSelIter = rItems.begin(); aSelIter != rItems.end(); ++aSelIter, ++nTargetIdx )
452 {
453 const TemplateViewItem *pViewItem = static_cast<const TemplateViewItem*>(*aSelIter);
454 sal_uInt16 nSrcRegionId = pViewItem->mnRegionId;
455
456 for (auto const & pRegion : maRegions)
457 {
458 if (pRegion->mnRegionId == nSrcRegionId)
459 pSrc = pRegion.get();
460 }
461
462 if(pSrc)
463 {
464 bool bCopy = !mpDocTemplates->Move(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnDocId);
465
466 if (bCopy)
467 {
468 OUString sQuery = SfxResId(STR_MSG_QUERY_COPY).replaceFirst("$1", pViewItem->maTitle).replaceFirst("$2",
469 getRegionName(nTargetRegion));
470 std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo, sQuery));
471 if (xQueryDlg->run() != RET_YES)
472 {
473 OUString sMsg(SfxResId(STR_MSG_ERROR_LOCAL_MOVE));
474 sMsg = sMsg.replaceFirst("$1",getRegionName(nTargetRegion));
475 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetDrawingArea(),
476 VclMessageType::Warning, VclButtonsType::Ok, sMsg.replaceFirst( "$2",pViewItem->maTitle)));
477 xBox->run();
478
479 return; //return if any single move operation fails
480 }
481
482 if (!mpDocTemplates->Copy(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnDocId))
483 {
484 continue;
485 }
486 }
487
488 // move template to destination
489
490 TemplateItemProperties aTemplateItem;
491 aTemplateItem.nId = nTargetIdx + 1;
492 aTemplateItem.nDocId = nTargetIdx;
493 aTemplateItem.nRegionId = nTargetRegion;
494 aTemplateItem.aName = pViewItem->maTitle;
495 aTemplateItem.aPath = mpDocTemplates->GetPath(nTargetRegion,nTargetIdx);
496 aTemplateItem.aRegionName = pViewItem->maHelpText;
497 aTemplateItem.aThumbnail = pViewItem->maPreview1;
498
499 pTarget->maTemplates.push_back(aTemplateItem);
500
501 if (!bCopy)
502 {
503 // remove template from region cached data
504
505 std::vector<TemplateItemProperties>::iterator pPropIter;
506 for (pPropIter = pSrc->maTemplates.begin(); pPropIter != pSrc->maTemplates.end();)
507 {
508 if (pPropIter->nDocId == pViewItem->mnDocId)
509 {
510 pPropIter = pSrc->maTemplates.erase(pPropIter);
511 aItemIds.push_back(pViewItem->mnDocId + 1);//mnid
512 }
513 else
514 {
515 // Keep region document id synchronized with SfxDocumentTemplates
516 if (pPropIter->nDocId > pViewItem->mnDocId)
517 --pPropIter->nDocId;
518
519 ++pPropIter;
520 }
521 }
522
523 // Keep view document id synchronized with SfxDocumentTemplates
524 for (auto const& item : mItemList)
525 {
526 auto pTemplateViewItem = static_cast<TemplateViewItem*>(item.get());
527 if (pTemplateViewItem->mnDocId > pViewItem->mnDocId)
528 --pTemplateViewItem->mnDocId;
529 }
530 }
531 }
532
533 refresh = true;
534 }
535
536 // Remove items from the current view
537 for (auto const& itemId : aItemIds)
538 RemoveItem(itemId);
539
540 if (refresh)
541 {
543 Invalidate();
544 }
545}
546
547bool TemplateLocalView::copyFrom (TemplateContainerItem *pItem, const OUString &rPath)
548{
549 sal_uInt16 nId = 1;
550 sal_uInt16 nDocId = 0;
551 sal_uInt16 nRegionId = pItem->mnRegionId;
552 OUString aPath(rPath);
553
554 if (!pItem->maTemplates.empty())
555 {
556 nId = pItem->maTemplates.back().nId+1;
557 nDocId = pItem->maTemplates.back().nDocId+1;
558 }
559
560 if (mpDocTemplates->CopyFrom(nRegionId,nDocId,aPath))
561 {
562 TemplateItemProperties aTemplate;
563 aTemplate.nId = nId;
564 aTemplate.nDocId = nDocId;
565 aTemplate.nRegionId = nRegionId;
566 aTemplate.aName = aPath;
570 aTemplate.aPath = rPath;
571 aTemplate.aRegionName = getRegionName(nRegionId);
572
573 pItem->maTemplates.push_back(aTemplate);
574
576
577 return true;
578 }
579
580 return false;
581}
582
583bool TemplateLocalView::exportTo(const sal_uInt16 nItemId, const sal_uInt16 nRegionItemId, std::u16string_view rName)
584{
585 for (auto const & pRegItem : maRegions)
586 {
587 if (pRegItem->mnId == nRegionItemId)
588 {
589 for (auto const& elem : pRegItem->maTemplates)
590 {
591 if (elem.nId == nItemId)
592 {
593 return mpDocTemplates->CopyTo(pRegItem->mnRegionId,elem.nDocId,rName);
594 }
595 }
596
597 break;
598 }
599 }
600
601 return false;
602}
603
604bool TemplateLocalView::renameItem(ThumbnailViewItem* pItem, const OUString& sNewTitle)
605{
606 sal_uInt16 nRegionId = 0;
607 sal_uInt16 nDocId = USHRT_MAX;
608 TemplateViewItem* pDocItem = dynamic_cast<TemplateViewItem*>( pItem );
609
610 if ( pDocItem )
611 {
612 nRegionId = pDocItem->mnRegionId;
613 nDocId = pDocItem->mnDocId;
614 }
615
616 bool bRes = mpDocTemplates->SetName( sNewTitle, nRegionId, nDocId );
617 if(bRes)
618 {
619 for (auto & pRegion : maRegions)
620 {
621 if (pRegion->mnId == nRegionId + 1 )
622 {
623 for(auto & aTemplate : pRegion->maTemplates)
624 {
625 if(aTemplate.nId == nDocId + 1)
626 {
627 aTemplate.aName = sNewTitle;
628 break;
629 }
630 }
631 break;
632 }
633 }
634 OUString sRegionName;
635 for (auto & aTemplate : maAllTemplates)
636 {
637 if (aTemplate.nRegionId == nRegionId && aTemplate.nDocId == nDocId)
638 {
639 aTemplate.aName = sNewTitle;
640 sRegionName = aTemplate.aRegionName;
641 break;
642 }
643 }
644
645 OUString sHelpText = SfxResId(STR_TEMPLATE_TOOLTIP);
646 sHelpText = (sHelpText.replaceFirst("$1", sNewTitle)).replaceFirst("$2", sRegionName);
647 pItem->setHelpText(sHelpText);
648 pItem->maTitle = sNewTitle;
649 }
650 return bRes;
651}
652
653void TemplateLocalView::insertItems(const std::vector<TemplateItemProperties> &rTemplates, bool isRegionSelected, bool bShowCategoryInTooltip)
654{
655 std::vector<std::unique_ptr<ThumbnailViewItem>> aItems(rTemplates.size());
656 for (size_t i = 0, n = rTemplates.size(); i < n; ++i )
657 {
658 const TemplateItemProperties *pCur = &rTemplates[i];
659
660 std::unique_ptr<TemplateViewItem> pChild;
661 if(isRegionSelected)
662 pChild.reset(new TemplateViewItem(*this, pCur->nId));
663 else
664 pChild.reset(new TemplateViewItem(*this, i+1));
665
666 pChild->mnDocId = pCur->nDocId;
667 pChild->mnRegionId = pCur->nRegionId;
668 pChild->maTitle = pCur->aName;
669 pChild->setPath(pCur->aPath);
670
671 if(!bShowCategoryInTooltip)
672 pChild->setHelpText(pCur->aName);
673 else
674 {
675 OUString sHelpText = SfxResId(STR_TEMPLATE_TOOLTIP);
676 sHelpText = (sHelpText.replaceFirst("$1", pCur->aName)).replaceFirst("$2", pCur->aRegionName);
677 pChild->setHelpText(sHelpText);
678 }
679
680 pChild->maPreview1 = pCur->aThumbnail;
681
682 if(IsDefaultTemplate(pCur->aPath))
683 pChild->showDefaultIcon(true);
684
685 if ( pCur->aThumbnail.IsEmpty() )
686 {
687 // Use the default thumbnail if we have nothing else
688 pChild->maPreview1 = TemplateLocalView::getDefaultThumbnail(pCur->aPath);
689 }
690
691 aItems[i] = std::move(pChild);
692 }
693
694 updateItems(std::move(aItems));
695}
696
698{
699 GrabFocus();
700 return ThumbnailView::MouseButtonDown(rMEvt);
701}
702
704{
705 if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
706 return CustomWidgetController::Command(rCEvt);
707
708 if (rCEvt.IsMouseEvent())
709 {
710 size_t nPos = ImplGetItem(rCEvt.GetMousePosPixel());
711 Point aPosition(rCEvt.GetMousePosPixel());
712 maPosition = aPosition;
714 const TemplateViewItem *pViewItem = dynamic_cast<const TemplateViewItem*>(pItem);
715
716 if(pViewItem)
717 {
718 if(!pItem->isSelected())
719 {
721 pItem->setSelection(true);
722 maItemStateHdl.Call(pItem);
723 }
724 maSelectedItem = dynamic_cast<TemplateViewItem*>(pItem);
726 }
727 }
728 else
729 {
731 {
732 if (pItem->isSelected())
733 {
734 tools::Rectangle aRect = pItem->getDrawArea();
735 maPosition = aRect.Center();
736 maSelectedItem = dynamic_cast<TemplateViewItem*>(pItem);
738 break;
739 }
740 }
741 }
742 return true;
743}
744
746{
747 vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
748
749 if(aKeyCode == ( KEY_MOD1 | KEY_A ) )
750 {
752 {
753 if (!pItem->isSelected())
754 {
755 pItem->setSelection(true);
756 maItemStateHdl.Call(pItem);
757 }
758 }
759
760 if (IsReallyVisible() && IsUpdateMode())
761 Invalidate();
762 return true;
763 }
764 else if( aKeyCode == KEY_DELETE && !mFilteredItemList.empty())
765 {
766 std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo,
767 SfxResId(STR_QMSG_SEL_TEMPLATE_DELETE)));
768 if (xQueryDlg->run() != RET_YES)
769 return true;
770
771 //copy to avoid changing filtered item list during deletion
772 ThumbnailValueItemList mFilteredItemListCopy = mFilteredItemList;
773
774 for (ThumbnailViewItem* pItem : mFilteredItemListCopy)
775 {
776 if (pItem->isSelected())
777 {
779 }
780 }
781 reload();
782 }
783
784 return ThumbnailView::KeyInput(rKEvt);
785}
786
788{
789 maOpenRegionHdl = rLink;
790}
791
793{
795}
796
798{
799 maOpenTemplateHdl = rLink;
800}
801
803{
804 maEditTemplateHdl = rLink;
805}
806
808{
809 maDeleteTemplateHdl = rLink;
810}
811
813{
814 maDefaultTemplateHdl = rLink;
815}
816
818{
819 maMoveTemplateHdl = rLink;
820}
821
823{
824 maExportTemplateHdl = rLink;
825}
826
828{
829 BitmapEx aImg = rImg;
830
831 if (!rImg.IsEmpty())
832 {
833 Size aSize = rImg.GetSizePixel();
834
835 if (aSize.Width() == 0)
836 aSize.setWidth( 1 );
837
838 if (aSize.Height() == 0)
839 aSize.setHeight( 1 );
840
841 // make the picture fit the given width/height constraints
842 double nRatio = std::min(double(width)/double(aSize.Width()), double(height)/double(aSize.Height()));
843
844 aImg.Scale(nRatio, nRatio);
845 }
846
847 return aImg;
848}
849
850bool TemplateLocalView::IsDefaultTemplate(const OUString& rPath)
851{
852 SvtModuleOptions aModOpt;
853 const css::uno::Sequence<OUString> &aServiceNames = aModOpt.GetAllServiceNames();
854
855 return std::any_of(aServiceNames.begin(), aServiceNames.end(), [&rPath](const OUString& rName) {
856 return SfxObjectFactory::GetStandardTemplate(rName).match(rPath); });
857}
858
859void TemplateLocalView::RemoveDefaultTemplateIcon(std::u16string_view rPath)
860{
861 for (const std::unique_ptr<ThumbnailViewItem>& pItem : mItemList)
862 {
863 TemplateViewItem* pViewItem = dynamic_cast<TemplateViewItem*>(pItem.get());
864 if (pViewItem && pViewItem->getPath().match(rPath))
865 {
866 pViewItem->showDefaultIcon(false);
867 Invalidate();
868 return;
869 }
870 }
871}
872
874{
875 BitmapEx aImg;
876 INetURLObject aUrl(rPath);
877 OUString aExt = aUrl.getExtension();
878
880 aImg = BitmapEx(SFX_THUMBNAIL_TEXT);
882 aImg = BitmapEx(SFX_THUMBNAIL_SHEET);
884 aImg = BitmapEx(SFX_THUMBNAIL_PRESENTATION);
886 aImg = BitmapEx(SFX_THUMBNAIL_DRAWING);
887
888 return aImg;
889}
890
892{
893 return TemplateLocalView::scaleImg(ThumbnailView::readThumbnail(msURL), width, height);
894}
895
897{
898 TemplateViewItem* pViewItem = dynamic_cast<TemplateViewItem*>(pItem);
899
900 if( pViewItem )
901 maOpenTemplateHdl.Call(pViewItem);
902}
903
904bool TemplateLocalView::IsInternalTemplate(const OUString& rPath)
905{
906 uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
907 css::uno::Reference< css::util::XPathSettings > xPathSettings = css::util::thePathSettings::get(xContext);
908 uno::Sequence<OUString> aInternalTemplateDirs;
909 uno::Any aAny = xPathSettings->getPropertyValue("Template_internal");
910 aAny >>= aInternalTemplateDirs;
911 SfxURLRelocator_Impl aRelocator(xContext);
912 for (OUString& rInternalTemplateDir : asNonConstRange(aInternalTemplateDirs))
913 {
914 aRelocator.makeRelocatableURL(rInternalTemplateDir);
915 aRelocator.makeAbsoluteURL(rInternalTemplateDir);
916 if(::utl::UCBContentHelper::IsSubPath(rInternalTemplateDir, rPath))
917 return true;
918 }
919 return false;
920}
921
922bool TemplateLocalView::IsBuiltInRegion(const OUString& rRegionName)
923{
924 bool isBuiltInCategory = false;
926 isBuiltInCategory = std::find(aGroupNames.begin(), aGroupNames.end(),
927 rRegionName) != aGroupNames.end();
928 if(isBuiltInCategory)
929 return true;
930 //check if it contains any internal template
931 for(const auto& rItem : maRegions)
932 {
933 if(rItem->maTitle == rRegionName)
934 {
935 for(const auto& rTemplateItem : rItem->maTemplates)
936 {
937 if(IsInternalTemplate(rTemplateItem.aPath))
938 return true;
939 }
940 break;
941 }
942 }
943 return false;
944}
945/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
geometry::RealPoint2D maPosition
PropertiesInfo aProperties
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
bool IsEmpty() const
const Size & GetSizePixel() const
CommandEventId GetCommand() const
const Point & GetMousePosPixel() const
bool IsMouseEvent() const
static std::vector< OUString > GetBuiltInGroupNames()
OUString getExtension(sal_Int32 nIndex=LAST_SEGMENT, bool bIgnoreFinalSlash=true, DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
OUString GetEntryText() const
Definition: inputdlg.cxx:24
void setCheckEntry(std::function< bool(OUString)> aFunc)
Definition: inputdlg.cxx:54
void SetEntryText(const OUString &rStr)
Definition: inputdlg.cxx:26
void HideHelpBtn()
Definition: inputdlg.cxx:22
const vcl::KeyCode & GetKeyCode() const
void makeAbsoluteURL(OUString &rURL)
void makeRelocatableURL(OUString &rURL)
constexpr tools::Long Height() const
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
css::uno::Sequence< OUString > GetAllServiceNames()
std::vector< TemplateItemProperties > maTemplates
bool exportTo(const sal_uInt16 nItemId, const sal_uInt16 nRegionItemId, std::u16string_view rName)
tools::Long mnThumbnailWidth
TemplateLocalView(std::unique_ptr< weld::ScrolledWindow > xWindow, std::unique_ptr< weld::Menu > xMenu)
std::vector< TemplateItemProperties > maAllTemplates
void RemoveDefaultTemplateIcon(std::u16string_view rPath)
TemplateContainerItem * getRegion(std::u16string_view sStr)
bool IsBuiltInRegion(const OUString &rRegionName)
static BitmapEx getDefaultThumbnail(std::u16string_view rPath)
static bool IsInternalTemplate(const OUString &rPath)
Link< ThumbnailViewItem *, void > maEditTemplateHdl
void ContextMenuSelectHdl(std::u16string_view rIdent)
void setMoveTemplateHdl(const Link< void *, void > &rLink)
OUString getRegionName(const sal_uInt16 nRegionId) const
void setCreateContextMenuHdl(const Link< ThumbnailViewItem *, void > &rLink)
Link< ThumbnailViewItem *, void > maDefaultTemplateHdl
bool removeTemplate(const sal_uInt16 nItemId, const sal_uInt16 nSrcItemId)
sal_uInt16 getRegionId(size_t pos) const
virtual void OnItemDblClicked(ThumbnailViewItem *pItem) override
void moveTemplates(const std::set< const ThumbnailViewItem *, selection_cmp_fn > &rItems, const sal_uInt16 nTargetItem)
OUString getRegionItemName(const sal_uInt16 nItemId) const
sal_uInt16 createRegion(const OUString &rName)
static BitmapEx fetchThumbnail(const OUString &msURL, tools::Long width, tools::Long height)
virtual bool Command(const CommandEvent &rPos) override
void setEditTemplateHdl(const Link< ThumbnailViewItem *, void > &rLink)
Link< ThumbnailViewItem *, void > maCreateContextMenuHdl
void showRegion(TemplateContainerItem const *pItem)
std::vector< OUString > getFolderNames()
Link< void *, void > maOpenRegionHdl
Link< void *, void > maExportTemplateHdl
virtual bool renameItem(ThumbnailViewItem *pItem, const OUString &sNewTitle) override
void setDeleteTemplateHdl(const Link< void *, void > &rLink)
void setExportTemplateHdl(const Link< void *, void > &rLink)
virtual ~TemplateLocalView() override
void updateThumbnailDimensions(tools::Long itemMaxSize)
Link< void *, void > maDeleteTemplateHdl
virtual bool KeyInput(const KeyEvent &rKEvt) override
void setDefaultTemplateHdl(const Link< ThumbnailViewItem *, void > &rLink)
std::unique_ptr< SfxDocumentTemplates > mpDocTemplates
std::vector< TemplateItemProperties > getFilteredItems(const std::function< bool(const TemplateItemProperties &) > &rFunc) const
bool copyFrom(TemplateContainerItem *pItem, const OUString &rPath)
tools::Long mnThumbnailHeight
void insertItems(const std::vector< TemplateItemProperties > &rTemplates, bool isRegionSelected=true, bool bShowCategoryInTooltip=false)
Link< ThumbnailViewItem *, void > maOpenTemplateHdl
bool removeRegion(const sal_uInt16 nItemId)
std::vector< std::unique_ptr< TemplateContainerItem > > maRegions
TemplateViewItem * maSelectedItem
void setOpenTemplateHdl(const Link< ThumbnailViewItem *, void > &rLink)
virtual bool MouseButtonDown(const MouseEvent &rMEvt) override
Link< void *, void > maMoveTemplateHdl
void setOpenRegionHdl(const Link< void *, void > &rLink)
static bool IsDefaultTemplate(const OUString &rPath)
virtual void showAllTemplates()
bool renameRegion(std::u16string_view rTitle, const OUString &rNewTitle)
static BitmapEx scaleImg(const BitmapEx &rImg, tools::Long width, tools::Long height)
const OUString & getPath() const
void showDefaultIcon(bool bVal)
OUString const & getTitle() const
void setHelpText(const OUString &sText)
Text to be used for the tooltip.
void setSelection(bool state)
void setTitle(const OUString &rTitle)
Class to display thumbnails with their names below their respective icons.
void updateItems(std::vector< std::unique_ptr< ThumbnailViewItem > > items)
void CalculateItemPositions(bool bScrollBarUsed=false)
void deselectItems()
deselect all current selected items.
Link< const ThumbnailViewItem *, void > maItemStateHdl
virtual bool MouseButtonDown(const MouseEvent &rMEvt) override
size_t ImplGetItem(const Point &rPoint) const
virtual bool KeyInput(const KeyEvent &rKEvt) override
void RemoveItem(sal_uInt16 nItemId)
static BitmapEx readThumbnail(const OUString &msURL)
std::vector< std::unique_ptr< ThumbnailViewItem > > mItemList
ThumbnailValueItemList mFilteredItemList
Cache to store the filtered items.
static bool isFilteredExtension(FILTER_APPLICATION filter, std::u16string_view rExt)
FILTER_APPLICATION mApp
bool isValid(std::u16string_view rPath) const
bool operator()(const ThumbnailViewItem *pItem)
constexpr Point Center() const
weld::DrawingArea * GetDrawingArea() const
virtual short run()
int nCount
URL aURL
OUString maTitle
Definition: doctempl.cxx:108
float u
Sequence< OUString > aServiceNames
const sal_uInt16 aItemIds[]
OUString aName
sal_Int64 n
constexpr sal_uInt16 KEY_MOD1
constexpr sal_uInt16 KEY_A
constexpr sal_uInt16 KEY_DELETE
sal_uInt16 nPos
Definition: linksrc.cxx:118
OString strip(const OString &rIn, char c)
int i
long Long
sal_Int16 nId
OUString SfxResId(TranslateId aId)
Definition: sfxresid.cxx:22
sal_uInt16 nId
Index for ThumbnailView.
sal_uInt16 nDocId
Index based on SfxTemplateDocument.
FILTER_APPLICATION
#define TEMPLATE_THUMBNAIL_MAX_HEIGHT
#define TEMPLATE_THUMBNAIL_MAX_WIDTH
::std::vector< ThumbnailViewItem * > ThumbnailValueItemList
RET_YES
size_t pos