Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / control / templatelocalview.cxx
blob4063e3453aafd8f8f7ac476f2a34da4b87890031
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <sfx2/templatelocalview.hxx>
12 #include <comphelper/string.hxx>
13 #include <sfx2/doctempl.hxx>
14 #include <sfx2/inputdlg.hxx>
15 #include <sfx2/sfxresid.hxx>
16 #include <templatecontaineritem.hxx>
17 #include <templateviewitem.hxx>
18 #include <sfx2/docfac.hxx>
19 #include <tools/urlobj.hxx>
20 #include <unotools/moduleoptions.hxx>
21 #include <vcl/help.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/weld.hxx>
24 #include <vcl/commandevent.hxx>
25 #include <vcl/event.hxx>
27 #include <sfx2/strings.hrc>
28 #include <bitmaps.hlst>
30 using namespace ::com::sun::star;
32 bool ViewFilter_Application::isFilteredExtension(FILTER_APPLICATION filter, const OUString &rExt)
34 bool bRet = rExt == "ott" || rExt == "stw" || rExt == "oth" || rExt == "dot" || rExt == "dotx" || rExt == "otm"
35 || rExt == "ots" || rExt == "stc" || rExt == "xlt" || rExt == "xltm" || rExt == "xltx"
36 || rExt == "otp" || rExt == "sti" || rExt == "pot" || rExt == "potm" || rExt == "potx"
37 || rExt == "otg" || rExt == "std";
39 if (filter == FILTER_APPLICATION::WRITER)
41 bRet = rExt == "ott" || rExt == "stw" || rExt == "oth" || rExt == "dot" || rExt == "dotx" || rExt == "otm";
43 else if (filter == FILTER_APPLICATION::CALC)
45 bRet = rExt == "ots" || rExt == "stc" || rExt == "xlt" || rExt == "xltm" || rExt == "xltx";
47 else if (filter == FILTER_APPLICATION::IMPRESS)
49 bRet = rExt == "otp" || rExt == "sti" || rExt == "pot" || rExt == "potm" || rExt == "potx";
51 else if (filter == FILTER_APPLICATION::DRAW)
53 bRet = rExt == "otg" || rExt == "std";
56 return bRet;
59 bool ViewFilter_Application::isValid (const OUString &rPath) const
61 INetURLObject aUrl(rPath);
62 return isFilteredExtension(mApp, aUrl.getExtension());
65 bool ViewFilter_Application::operator () (const ThumbnailViewItem *pItem)
67 const TemplateViewItem *pTempItem = dynamic_cast<const TemplateViewItem*>(pItem);
68 if (pTempItem)
69 return isValid(pTempItem->getPath());
71 return true;
74 void TemplateLocalView::updateThumbnailDimensions(tools::Long itemMaxSize)
76 mnThumbnailWidth = itemMaxSize;
77 mnThumbnailHeight = itemMaxSize;
80 TemplateLocalView::TemplateLocalView(std::unique_ptr<weld::ScrolledWindow> xWindow,
81 std::unique_ptr<weld::Menu> xMenu)
82 : ThumbnailView(std::move(xWindow), std::move(xMenu))
83 , mnCurRegionId(0)
84 , maSelectedItem(nullptr)
85 , mnThumbnailWidth(TEMPLATE_THUMBNAIL_MAX_WIDTH)
86 , mnThumbnailHeight(TEMPLATE_THUMBNAIL_MAX_HEIGHT)
87 , maPosition(0,0)
88 , mpDocTemplates(new SfxDocumentTemplates)
92 TemplateLocalView::~TemplateLocalView()
96 void TemplateLocalView::Populate()
98 maRegions.clear();
99 maAllTemplates.clear();
101 sal_uInt16 nCount = mpDocTemplates->GetRegionCount();
102 for (sal_uInt16 i = 0; i < nCount; ++i)
104 OUString aRegionName(mpDocTemplates->GetFullRegionName(i));
106 std::unique_ptr<TemplateContainerItem> pItem(new TemplateContainerItem( i+1 ));
107 pItem->mnRegionId = i;
108 pItem->maTitle = aRegionName;
110 sal_uInt16 nEntries = mpDocTemplates->GetCount(i);
112 for (sal_uInt16 j = 0; j < nEntries; ++j)
114 OUString aName = mpDocTemplates->GetName(i,j);
115 OUString aURL = mpDocTemplates->GetPath(i,j);
117 TemplateItemProperties aProperties;
118 aProperties.nId = j+1;
119 aProperties.nDocId = j;
120 aProperties.nRegionId = i;
121 aProperties.aName = aName;
122 aProperties.aPath = aURL;
123 aProperties.aRegionName = aRegionName;
124 aProperties.aThumbnail = TemplateLocalView::fetchThumbnail(aURL,
125 mnThumbnailWidth,
126 mnThumbnailHeight);
128 pItem->maTemplates.push_back(aProperties);
129 maAllTemplates.push_back(aProperties);
132 maRegions.push_back(std::move(pItem));
136 void TemplateLocalView::reload()
138 mpDocTemplates->Update();
140 Populate();
142 // Check if we are currently browsing a region or root folder
143 if (mnCurRegionId)
145 sal_uInt16 nRegionId = mnCurRegionId - 1; //Is offset by 1
147 for (auto const & pRegion : maRegions)
149 if (pRegion->mnRegionId == nRegionId)
151 showRegion(pRegion.get());
152 break;
156 else
157 showAllTemplates();
159 //No items should be selected by default
160 deselectItems();
163 void TemplateLocalView::showAllTemplates()
165 mnCurRegionId = 0;
167 insertItems(maAllTemplates, false, true);
169 maOpenRegionHdl.Call(nullptr);
172 void TemplateLocalView::showRegion(TemplateContainerItem const *pItem)
174 mnCurRegionId = pItem->mnRegionId+1;
176 insertItems(pItem->maTemplates);
178 maOpenRegionHdl.Call(nullptr);
181 void TemplateLocalView::showRegion(const OUString &rName)
183 for (auto const & pRegion : maRegions)
185 if (pRegion->maTitle == rName)
187 showRegion(pRegion.get());
188 break;
193 TemplateContainerItem* TemplateLocalView::getRegion(OUString const & rName)
195 for (auto const & pRegion : maRegions)
196 if (pRegion->maTitle == rName)
197 return pRegion.get();
199 return nullptr;
202 void TemplateLocalView::createContextMenu(const bool bIsDefault)
204 mxContextMenu->clear();
205 mxContextMenu->append("open",SfxResId(STR_OPEN));
206 mxContextMenu->append("edit",SfxResId(STR_EDIT_TEMPLATE));
208 if(!bIsDefault)
209 mxContextMenu->append("default",SfxResId(STR_DEFAULT_TEMPLATE));
210 else
211 mxContextMenu->append("default",SfxResId(STR_RESET_DEFAULT));
213 mxContextMenu->append_separator("separator");
214 mxContextMenu->append("rename",SfxResId(STR_SFX_RENAME));
215 mxContextMenu->append("delete",SfxResId(STR_DELETE));
216 deselectItems();
217 maSelectedItem->setSelection(true);
218 maItemStateHdl.Call(maSelectedItem);
219 ContextMenuSelectHdl(mxContextMenu->popup_at_rect(GetDrawingArea(), tools::Rectangle(maPosition, Size(1,1))));
220 Invalidate();
223 void TemplateLocalView::ContextMenuSelectHdl(const OString& rIdent)
225 if (rIdent == "open")
226 maOpenTemplateHdl.Call(maSelectedItem);
227 else if (rIdent == "edit")
228 maEditTemplateHdl.Call(maSelectedItem);
229 else if (rIdent == "rename")
231 InputDialog aTitleEditDlg(GetDrawingArea(), SfxResId(STR_RENAME_TEMPLATE));
232 OUString sOldTitle = maSelectedItem->getTitle();
233 aTitleEditDlg.SetEntryText(sOldTitle);
234 aTitleEditDlg.HideHelpBtn();
236 if (!aTitleEditDlg.run())
237 return;
238 OUString sNewTitle = comphelper::string::strip(aTitleEditDlg.GetEntryText(), ' ');
240 if ( !sNewTitle.isEmpty() && sNewTitle != sOldTitle )
242 maSelectedItem->setTitle(sNewTitle);
245 else if (rIdent == "delete")
247 std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo,
248 SfxResId(STR_QMSG_SEL_TEMPLATE_DELETE)));
249 if (xQueryDlg->run() != RET_YES)
250 return;
252 maDeleteTemplateHdl.Call(maSelectedItem);
253 reload();
255 else if (rIdent == "default")
256 maDefaultTemplateHdl.Call(maSelectedItem);
259 sal_uInt16 TemplateLocalView::getRegionId(size_t pos) const
261 assert(pos < maRegions.size());
263 return maRegions[pos]->mnId;
266 sal_uInt16 TemplateLocalView::getRegionId(OUString const & sRegion) const
268 for (auto const & pRegion : maRegions)
270 if (pRegion->maTitle == sRegion)
271 return pRegion->mnId;
274 return 0;
277 OUString TemplateLocalView::getRegionName(const sal_uInt16 nRegionId) const
279 return mpDocTemplates->GetRegionName(nRegionId);
282 OUString TemplateLocalView::getRegionItemName(const sal_uInt16 nItemId) const
284 for (auto const & pRegion : maRegions)
286 if (pRegion->mnId == nItemId)
287 return pRegion->maTitle;
290 return OUString();
293 std::vector<OUString> TemplateLocalView::getFolderNames()
295 size_t n = maRegions.size();
296 std::vector<OUString> ret(n);
298 for (size_t i = 0; i < n; ++i)
299 ret[i] = maRegions[i]->maTitle;
301 return ret;
304 std::vector<TemplateItemProperties>
305 TemplateLocalView::getFilteredItems(const std::function<bool (const TemplateItemProperties&)> &rFunc) const
307 std::vector<TemplateItemProperties> aItems;
309 if (mnCurRegionId)
311 TemplateContainerItem *pFolderItem = maRegions[mnCurRegionId-1].get();
313 for (const TemplateItemProperties & rItemProps : pFolderItem->maTemplates)
315 if (rFunc(rItemProps))
316 aItems.push_back(rItemProps);
319 else
321 for (auto const & pFolderItem : maRegions)
323 for (const TemplateItemProperties & rItemProps : pFolderItem->maTemplates)
325 if (rFunc(rItemProps))
326 aItems.push_back(rItemProps);
331 return aItems;
334 sal_uInt16 TemplateLocalView::createRegion(const OUString &rName)
336 sal_uInt16 nRegionId = mpDocTemplates->GetRegionCount(); // Next regionId
337 sal_uInt16 nItemId = getNextItemId();
339 if (!mpDocTemplates->InsertDir(rName,nRegionId))
340 return 0;
342 // Insert to the region cache list and to the thumbnail item list
343 std::unique_ptr<TemplateContainerItem> pItem(new TemplateContainerItem( nItemId ));
344 pItem->mnRegionId = nRegionId;
345 pItem->maTitle = rName;
347 maRegions.push_back(std::move(pItem));
349 return nItemId;
352 bool TemplateLocalView::renameRegion(const OUString &rTitle, const OUString &rNewTitle)
354 TemplateContainerItem *pRegion = getRegion(rTitle);
356 if(pRegion)
358 sal_uInt16 nRegionId = pRegion->mnRegionId;
359 return mpDocTemplates->SetName( rNewTitle, nRegionId, USHRT_MAX/*nDocId*/ );
361 return false;
364 bool TemplateLocalView::removeRegion(const sal_uInt16 nItemId)
366 sal_uInt16 nRegionId = USHRT_MAX;
368 // Remove from the region cache list
369 for (auto pRegionIt = maRegions.begin(); pRegionIt != maRegions.end();)
371 if ( (*pRegionIt)->mnId == nItemId )
373 if (!mpDocTemplates->Delete((*pRegionIt)->mnRegionId,USHRT_MAX))
374 return false;
376 nRegionId = (*pRegionIt)->mnRegionId;
378 pRegionIt = maRegions.erase(pRegionIt);
380 else
382 // Synchronize regions cache ids with SfxDocumentTemplates
383 if (nRegionId != USHRT_MAX && (*pRegionIt)->mnRegionId > nRegionId)
384 --(*pRegionIt)->mnRegionId;
386 ++pRegionIt;
390 if (nRegionId == USHRT_MAX)
391 return false;
393 // Synchronize view regions ids with SfxDocumentTemplates
394 for (auto const& region : maRegions)
396 if (region->mnRegionId > nRegionId)
397 --region->mnRegionId;
400 return true;
403 bool TemplateLocalView::removeTemplate (const sal_uInt16 nItemId, const sal_uInt16 nSrcItemId)
405 for (auto const & pRegion : maRegions)
407 if (pRegion->mnId == nSrcItemId)
409 TemplateContainerItem *pItem = pRegion.get();
410 auto pIter = std::find_if(pItem->maTemplates.begin(), pItem->maTemplates.end(),
411 [nItemId](const TemplateItemProperties& rTemplate) { return rTemplate.nId == nItemId; });
412 if (pIter != pItem->maTemplates.end())
414 if (!mpDocTemplates->Delete(pItem->mnRegionId,pIter->nDocId))
415 return false;
417 pIter = pItem->maTemplates.erase(pIter);
419 if (pRegion->mnRegionId == mnCurRegionId-1)
421 RemoveItem(nItemId);
422 Invalidate();
425 // Update Doc Idx for all templates that follow
426 for (; pIter != pItem->maTemplates.end(); ++pIter)
427 pIter->nDocId = pIter->nDocId - 1;
430 CalculateItemPositions();
431 break;
435 return true;
438 bool TemplateLocalView::moveTemplate (const ThumbnailViewItem *pItem, const sal_uInt16 nSrcItem,
439 const sal_uInt16 nTargetItem)
441 TemplateContainerItem *pTarget = nullptr;
442 TemplateContainerItem *pSrc = nullptr;
444 for (auto const & pRegion : maRegions)
446 if (pRegion->mnId == nTargetItem)
447 pTarget = pRegion.get();
448 else if (pRegion->mnId == nSrcItem)
449 pSrc = pRegion.get();
452 if (pTarget && pSrc)
454 sal_uInt16 nSrcRegionId = pSrc->mnRegionId;
455 sal_uInt16 nTargetRegion = pTarget->mnRegionId;
456 sal_uInt16 nTargetIdx = mpDocTemplates->GetCount(nTargetRegion); // Next Idx
458 const TemplateViewItem *pViewItem = static_cast<const TemplateViewItem*>(pItem);
460 bool bCopy = !mpDocTemplates->Move(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnDocId);
462 if (bCopy)
464 OUString sQuery = SfxResId(STR_MSG_QUERY_COPY).replaceFirst("$1", pViewItem->maTitle).replaceFirst("$2",
465 getRegionName(nTargetRegion));
467 std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo, sQuery));
468 if (xQueryDlg->run() != RET_YES)
469 return false;
471 if (!mpDocTemplates->Copy(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnDocId))
472 return false;
474 // move template to destination
476 TemplateItemProperties aTemplateItem;
477 aTemplateItem.nId = nTargetIdx + 1;
478 aTemplateItem.nDocId = nTargetIdx;
479 aTemplateItem.nRegionId = nTargetRegion;
480 aTemplateItem.aName = pViewItem->maTitle;
481 aTemplateItem.aPath = mpDocTemplates->GetPath(nTargetRegion,nTargetIdx);
482 aTemplateItem.aRegionName = pViewItem->maHelpText;
483 aTemplateItem.aThumbnail = pViewItem->maPreview1;
485 pTarget->maTemplates.push_back(aTemplateItem);
487 if (!bCopy)
489 // remove template from region cached data
491 std::vector<TemplateItemProperties>::iterator aIter;
492 for (aIter = pSrc->maTemplates.begin(); aIter != pSrc->maTemplates.end();)
494 if (aIter->nDocId == pViewItem->mnDocId)
496 aIter = pSrc->maTemplates.erase(aIter);
498 else
500 // Keep region document id synchronized with SfxDocumentTemplates
501 if (aIter->nDocId > pViewItem->mnDocId)
502 --aIter->nDocId;
504 ++aIter;
508 // Keep view document id synchronized with SfxDocumentTemplates
509 for (auto const& item : mItemList)
511 auto pTemplateViewItem = static_cast<TemplateViewItem*>(item.get());
512 if (pTemplateViewItem->mnDocId > pViewItem->mnDocId)
513 --pTemplateViewItem->mnDocId;
517 CalculateItemPositions();
518 Invalidate();
520 return true;
523 return false;
526 void TemplateLocalView::moveTemplates(const std::set<const ThumbnailViewItem*, selection_cmp_fn> &rItems,
527 const sal_uInt16 nTargetItem)
529 TemplateContainerItem *pTarget = nullptr;
530 TemplateContainerItem *pSrc = nullptr;
532 for (auto const & pRegion : maRegions)
534 if (pRegion->mnId == nTargetItem)
535 pTarget = pRegion.get();
538 if (!pTarget)
539 return;
541 bool refresh = false;
543 sal_uInt16 nTargetRegion = pTarget->mnRegionId;
544 sal_uInt16 nTargetIdx = mpDocTemplates->GetCount(nTargetRegion); // Next Idx
545 std::vector<sal_uInt16> aItemIds; // List of moved items ids (also prevents the invalidation of rItems iterators when we remove them as we go)
547 std::set<const ThumbnailViewItem*,selection_cmp_fn>::const_iterator aSelIter;
548 for ( aSelIter = rItems.begin(); aSelIter != rItems.end(); ++aSelIter, ++nTargetIdx )
550 const TemplateViewItem *pViewItem = static_cast<const TemplateViewItem*>(*aSelIter);
551 sal_uInt16 nSrcRegionId = pViewItem->mnRegionId;
553 for (auto const & pRegion : maRegions)
555 if (pRegion->mnRegionId == nSrcRegionId)
556 pSrc = pRegion.get();
559 if(pSrc)
561 bool bCopy = !mpDocTemplates->Move(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnDocId);
563 if (bCopy)
565 OUString sQuery = SfxResId(STR_MSG_QUERY_COPY).replaceFirst("$1", pViewItem->maTitle).replaceFirst("$2",
566 getRegionName(nTargetRegion));
567 std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo, sQuery));
568 if (xQueryDlg->run() != RET_YES)
570 OUString sMsg(SfxResId(STR_MSG_ERROR_LOCAL_MOVE));
571 sMsg = sMsg.replaceFirst("$1",getRegionName(nTargetRegion));
572 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetDrawingArea(),
573 VclMessageType::Warning, VclButtonsType::Ok, sMsg.replaceFirst( "$2",pViewItem->maTitle)));
574 xBox->run();
576 return; //return if any single move operation fails
579 if (!mpDocTemplates->Copy(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnDocId))
581 continue;
585 // move template to destination
587 TemplateItemProperties aTemplateItem;
588 aTemplateItem.nId = nTargetIdx + 1;
589 aTemplateItem.nDocId = nTargetIdx;
590 aTemplateItem.nRegionId = nTargetRegion;
591 aTemplateItem.aName = pViewItem->maTitle;
592 aTemplateItem.aPath = mpDocTemplates->GetPath(nTargetRegion,nTargetIdx);
593 aTemplateItem.aRegionName = pViewItem->maHelpText;
594 aTemplateItem.aThumbnail = pViewItem->maPreview1;
596 pTarget->maTemplates.push_back(aTemplateItem);
598 if (!bCopy)
600 // remove template from region cached data
602 std::vector<TemplateItemProperties>::iterator pPropIter;
603 for (pPropIter = pSrc->maTemplates.begin(); pPropIter != pSrc->maTemplates.end();)
605 if (pPropIter->nDocId == pViewItem->mnDocId)
607 pPropIter = pSrc->maTemplates.erase(pPropIter);
608 aItemIds.push_back(pViewItem->mnDocId + 1);//mnid
610 else
612 // Keep region document id synchronized with SfxDocumentTemplates
613 if (pPropIter->nDocId > pViewItem->mnDocId)
614 --pPropIter->nDocId;
616 ++pPropIter;
620 // Keep view document id synchronized with SfxDocumentTemplates
621 for (auto const& item : mItemList)
623 auto pTemplateViewItem = static_cast<TemplateViewItem*>(item.get());
624 if (pTemplateViewItem->mnDocId > pViewItem->mnDocId)
625 --pTemplateViewItem->mnDocId;
630 refresh = true;
633 // Remove items from the current view
634 for (auto const& itemId : aItemIds)
635 RemoveItem(itemId);
637 if (refresh)
639 CalculateItemPositions();
640 Invalidate();
644 bool TemplateLocalView::copyFrom (TemplateContainerItem *pItem, const OUString &rPath)
646 sal_uInt16 nId = 1;
647 sal_uInt16 nDocId = 0;
648 sal_uInt16 nRegionId = pItem->mnRegionId;
649 OUString aPath(rPath);
651 if (!pItem->maTemplates.empty())
653 nId = pItem->maTemplates.back().nId+1;
654 nDocId = pItem->maTemplates.back().nDocId+1;
657 if (mpDocTemplates->CopyFrom(nRegionId,nDocId,aPath))
659 TemplateItemProperties aTemplate;
660 aTemplate.nId = nId;
661 aTemplate.nDocId = nDocId;
662 aTemplate.nRegionId = nRegionId;
663 aTemplate.aName = aPath;
664 aTemplate.aThumbnail = TemplateLocalView::fetchThumbnail(rPath,
665 TEMPLATE_THUMBNAIL_MAX_WIDTH,
666 TEMPLATE_THUMBNAIL_MAX_HEIGHT);
667 aTemplate.aPath = rPath;
668 aTemplate.aRegionName = getRegionName(nRegionId);
670 pItem->maTemplates.push_back(aTemplate);
672 CalculateItemPositions();
674 return true;
677 return false;
680 bool TemplateLocalView::exportTo(const sal_uInt16 nItemId, const sal_uInt16 nRegionItemId, const OUString &rName)
682 for (auto const & pRegItem : maRegions)
684 if (pRegItem->mnId == nRegionItemId)
686 for (auto const& elem : pRegItem->maTemplates)
688 if (elem.nId == nItemId)
690 return mpDocTemplates->CopyTo(pRegItem->mnRegionId,elem.nDocId,rName);
694 break;
698 return false;
701 bool TemplateLocalView::renameItem(ThumbnailViewItem* pItem, const OUString& sNewTitle)
703 sal_uInt16 nRegionId = 0;
704 sal_uInt16 nDocId = USHRT_MAX;
705 TemplateViewItem* pDocItem = dynamic_cast<TemplateViewItem*>( pItem );
707 if ( pDocItem )
709 nRegionId = pDocItem->mnRegionId;
710 nDocId = pDocItem->mnDocId;
713 return mpDocTemplates->SetName( sNewTitle, nRegionId, nDocId );
716 void TemplateLocalView::insertItems(const std::vector<TemplateItemProperties> &rTemplates, bool isRegionSelected, bool bShowCategoryInTooltip)
718 std::vector<std::unique_ptr<ThumbnailViewItem>> aItems(rTemplates.size());
719 for (size_t i = 0, n = rTemplates.size(); i < n; ++i )
721 const TemplateItemProperties *pCur = &rTemplates[i];
723 std::unique_ptr<TemplateViewItem> pChild;
724 if(isRegionSelected)
725 pChild.reset(new TemplateViewItem(*this, pCur->nId));
726 else
727 pChild.reset(new TemplateViewItem(*this, i+1));
729 pChild->mnDocId = pCur->nDocId;
730 pChild->mnRegionId = pCur->nRegionId;
731 pChild->maTitle = pCur->aName;
732 pChild->setPath(pCur->aPath);
734 if(!bShowCategoryInTooltip)
735 pChild->setHelpText(pCur->aName);
736 else
738 OUString sHelpText = SfxResId(STR_TEMPLATE_TOOLTIP);
739 sHelpText = (sHelpText.replaceFirst("$1", pCur->aName)).replaceFirst("$2", pCur->aRegionName);
740 pChild->setHelpText(sHelpText);
743 pChild->maPreview1 = pCur->aThumbnail;
745 if(IsDefaultTemplate(pCur->aPath))
746 pChild->showDefaultIcon(true);
748 if ( pCur->aThumbnail.IsEmpty() )
750 // Use the default thumbnail if we have nothing else
751 pChild->maPreview1 = TemplateLocalView::getDefaultThumbnail(pCur->aPath);
754 aItems[i] = std::move(pChild);
757 updateItems(std::move(aItems));
760 bool TemplateLocalView::MouseButtonDown( const MouseEvent& rMEvt )
762 GrabFocus();
763 return ThumbnailView::MouseButtonDown(rMEvt);
766 bool TemplateLocalView::Command(const CommandEvent& rCEvt)
768 if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
769 return CustomWidgetController::Command(rCEvt);
771 if (rCEvt.IsMouseEvent())
773 deselectItems();
774 size_t nPos = ImplGetItem(rCEvt.GetMousePosPixel());
775 Point aPosition(rCEvt.GetMousePosPixel());
776 maPosition = aPosition;
777 ThumbnailViewItem* pItem = ImplGetItem(nPos);
778 const TemplateViewItem *pViewItem = dynamic_cast<const TemplateViewItem*>(pItem);
780 if(pViewItem)
782 maSelectedItem = dynamic_cast<TemplateViewItem*>(pItem);
783 maCreateContextMenuHdl.Call(pItem);
786 else
788 for (ThumbnailViewItem* pItem : mFilteredItemList)
790 //create context menu for the first selected item
791 if (pItem->isSelected())
793 deselectItems();
794 pItem->setSelection(true);
795 maItemStateHdl.Call(pItem);
796 tools::Rectangle aRect = pItem->getDrawArea();
797 maPosition = aRect.Center();
798 maSelectedItem = dynamic_cast<TemplateViewItem*>(pItem);
799 maCreateContextMenuHdl.Call(pItem);
800 break;
804 return true;
807 bool TemplateLocalView::KeyInput( const KeyEvent& rKEvt )
809 vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
811 if(aKeyCode == ( KEY_MOD1 | KEY_A ) )
813 for (ThumbnailViewItem* pItem : mFilteredItemList)
815 if (!pItem->isSelected())
817 pItem->setSelection(true);
818 maItemStateHdl.Call(pItem);
822 if (IsReallyVisible() && IsUpdateMode())
823 Invalidate();
824 return true;
826 else if( aKeyCode == KEY_DELETE && !mFilteredItemList.empty())
828 std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo,
829 SfxResId(STR_QMSG_SEL_TEMPLATE_DELETE)));
830 if (xQueryDlg->run() != RET_YES)
831 return true;
833 //copy to avoid changing filtered item list during deletion
834 ThumbnailValueItemList mFilteredItemListCopy = mFilteredItemList;
836 for (ThumbnailViewItem* pItem : mFilteredItemListCopy)
838 if (pItem->isSelected())
840 maDeleteTemplateHdl.Call(pItem);
843 reload();
846 return ThumbnailView::KeyInput(rKEvt);
849 void TemplateLocalView::setOpenRegionHdl(const Link<void*,void> &rLink)
851 maOpenRegionHdl = rLink;
854 void TemplateLocalView::setCreateContextMenuHdl(const Link<ThumbnailViewItem*,void> &rLink)
856 maCreateContextMenuHdl = rLink;
859 void TemplateLocalView::setOpenTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink)
861 maOpenTemplateHdl = rLink;
864 void TemplateLocalView::setEditTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink)
866 maEditTemplateHdl = rLink;
869 void TemplateLocalView::setDeleteTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink)
871 maDeleteTemplateHdl = rLink;
874 void TemplateLocalView::setDefaultTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink)
876 maDefaultTemplateHdl = rLink;
879 BitmapEx TemplateLocalView::scaleImg (const BitmapEx &rImg, tools::Long width, tools::Long height)
881 BitmapEx aImg = rImg;
883 if (!rImg.IsEmpty())
885 Size aSize = rImg.GetSizePixel();
887 if (aSize.Width() == 0)
888 aSize.setWidth( 1 );
890 if (aSize.Height() == 0)
891 aSize.setHeight( 1 );
893 // make the picture fit the given width/height constraints
894 double nRatio = std::min(double(width)/double(aSize.Width()), double(height)/double(aSize.Height()));
896 aImg.Scale(Size(aSize.Width() * nRatio, aSize.Height() * nRatio));
899 return aImg;
902 bool TemplateLocalView::IsDefaultTemplate(const OUString& rPath)
904 SvtModuleOptions aModOpt;
905 const css::uno::Sequence<OUString> &aServiceNames = aModOpt.GetAllServiceNames();
907 return std::any_of(aServiceNames.begin(), aServiceNames.end(), [&rPath](const OUString& rName) {
908 return SfxObjectFactory::GetStandardTemplate(rName).match(rPath); });
911 void TemplateLocalView::RemoveDefaultTemplateIcon(std::u16string_view rPath)
913 for (const std::unique_ptr<ThumbnailViewItem>& pItem : mItemList)
915 TemplateViewItem* pViewItem = dynamic_cast<TemplateViewItem*>(pItem.get());
916 if (pViewItem && pViewItem->getPath().match(rPath))
918 pViewItem->showDefaultIcon(false);
919 Invalidate();
920 return;
925 BitmapEx TemplateLocalView::getDefaultThumbnail( const OUString& rPath )
927 BitmapEx aImg;
928 INetURLObject aUrl(rPath);
929 OUString aExt = aUrl.getExtension();
931 if ( ViewFilter_Application::isFilteredExtension( FILTER_APPLICATION::WRITER, aExt) )
932 aImg = BitmapEx(SFX_THUMBNAIL_TEXT);
933 else if ( ViewFilter_Application::isFilteredExtension( FILTER_APPLICATION::CALC, aExt) )
934 aImg = BitmapEx(SFX_THUMBNAIL_SHEET);
935 else if ( ViewFilter_Application::isFilteredExtension( FILTER_APPLICATION::IMPRESS, aExt) )
936 aImg = BitmapEx(SFX_THUMBNAIL_PRESENTATION);
937 else if ( ViewFilter_Application::isFilteredExtension( FILTER_APPLICATION::DRAW, aExt) )
938 aImg = BitmapEx(SFX_THUMBNAIL_DRAWING);
940 return aImg;
943 BitmapEx TemplateLocalView::fetchThumbnail (const OUString &msURL, tools::Long width, tools::Long height)
945 return TemplateLocalView::scaleImg(ThumbnailView::readThumbnail(msURL), width, height);
948 void TemplateLocalView::OnItemDblClicked (ThumbnailViewItem *pItem)
950 TemplateViewItem* pViewItem = dynamic_cast<TemplateViewItem*>(pItem);
952 if( pViewItem )
953 maOpenTemplateHdl.Call(pViewItem);
957 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */