diff options
Diffstat (limited to 'sfx2/source/control/templatelocalview.cxx')
-rw-r--r-- | sfx2/source/control/templatelocalview.cxx | 945 |
1 files changed, 945 insertions, 0 deletions
diff --git a/sfx2/source/control/templatelocalview.cxx b/sfx2/source/control/templatelocalview.cxx new file mode 100644 index 0000000000..bd5fd7f649 --- /dev/null +++ b/sfx2/source/control/templatelocalview.cxx @@ -0,0 +1,945 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sfx2/templatelocalview.hxx> + +#include <comphelper/string.hxx> +#include <sfx2/doctempl.hxx> +#include <sfx2/inputdlg.hxx> +#include <sfx2/sfxresid.hxx> +#include <templatecontaineritem.hxx> +#include <templateviewitem.hxx> +#include <sfx2/docfac.hxx> +#include <tools/urlobj.hxx> +#include <unotools/moduleoptions.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <vcl/commandevent.hxx> +#include <vcl/event.hxx> + +#include <sfx2/strings.hrc> +#include <bitmaps.hlst> + +#include <comphelper/processfactory.hxx> +#include <com/sun/star/util/thePathSettings.hpp> +#include <unotools/ucbhelper.hxx> +#include <sfxurlrelocator.hxx> +#include <../doc/doctemplateslocal.hxx> + +using namespace ::com::sun::star; + +bool ViewFilter_Application::isFilteredExtension(FILTER_APPLICATION filter, std::u16string_view rExt) +{ + bool bRet = rExt == u"ott" || rExt == u"stw" || rExt == u"oth" || rExt == u"dot" || rExt == u"dotx" || rExt == u"otm" + || rExt == u"ots" || rExt == u"stc" || rExt == u"xlt" || rExt == u"xltm" || rExt == u"xltx" + || rExt == u"otp" || rExt == u"sti" || rExt == u"pot" || rExt == u"potm" || rExt == u"potx" + || rExt == u"otg" || rExt == u"std"; + + if (filter == FILTER_APPLICATION::WRITER) + { + bRet = rExt == u"ott" || rExt == u"stw" || rExt == u"oth" || rExt == u"dot" || rExt == u"dotx" || rExt == u"otm"; + } + else if (filter == FILTER_APPLICATION::CALC) + { + bRet = rExt == u"ots" || rExt == u"stc" || rExt == u"xlt" || rExt == u"xltm" || rExt == u"xltx"; + } + else if (filter == FILTER_APPLICATION::IMPRESS) + { + bRet = rExt == u"otp" || rExt == u"sti" || rExt == u"pot" || rExt == u"potm" || rExt == u"potx"; + } + else if (filter == FILTER_APPLICATION::DRAW) + { + bRet = rExt == u"otg" || rExt == u"std"; + } + + return bRet; +} + +bool ViewFilter_Application::isValid (std::u16string_view rPath) const +{ + INetURLObject aUrl(rPath); + return isFilteredExtension(mApp, aUrl.getExtension()); +} + +bool ViewFilter_Application::operator () (const ThumbnailViewItem *pItem) +{ + const TemplateViewItem *pTempItem = dynamic_cast<const TemplateViewItem*>(pItem); + if (pTempItem) + return isValid(pTempItem->getPath()); + + return true; +} + +void TemplateLocalView::updateThumbnailDimensions(tools::Long itemMaxSize) +{ + mnThumbnailWidth = itemMaxSize; + mnThumbnailHeight = itemMaxSize; +} + +TemplateLocalView::TemplateLocalView(std::unique_ptr<weld::ScrolledWindow> xWindow, + std::unique_ptr<weld::Menu> xMenu) + : ThumbnailView(std::move(xWindow), std::move(xMenu)) + , mnCurRegionId(0) + , maSelectedItem(nullptr) + , mnThumbnailWidth(TEMPLATE_THUMBNAIL_MAX_WIDTH) + , mnThumbnailHeight(TEMPLATE_THUMBNAIL_MAX_HEIGHT) + , maPosition(0,0) + , mpDocTemplates(new SfxDocumentTemplates) +{ +} + +TemplateLocalView::~TemplateLocalView() +{ +} + +void TemplateLocalView::Populate() +{ + maRegions.clear(); + maAllTemplates.clear(); + + sal_uInt16 nCount = mpDocTemplates->GetRegionCount(); + for (sal_uInt16 i = 0; i < nCount; ++i) + { + OUString aRegionName(mpDocTemplates->GetFullRegionName(i)); + + std::unique_ptr<TemplateContainerItem> pItem(new TemplateContainerItem( i+1 )); + pItem->mnRegionId = i; + pItem->maTitle = aRegionName; + + sal_uInt16 nEntries = mpDocTemplates->GetCount(i); + + for (sal_uInt16 j = 0; j < nEntries; ++j) + { + OUString aName = mpDocTemplates->GetName(i,j); + OUString aURL = mpDocTemplates->GetPath(i,j); + + TemplateItemProperties aProperties; + aProperties.nId = j+1; + aProperties.nDocId = j; + aProperties.nRegionId = i; + aProperties.aName = aName; + aProperties.aPath = aURL; + aProperties.aRegionName = aRegionName; + aProperties.aThumbnail = TemplateLocalView::fetchThumbnail(aURL, + mnThumbnailWidth, + mnThumbnailHeight); + + pItem->maTemplates.push_back(aProperties); + maAllTemplates.push_back(aProperties); + } + + maRegions.push_back(std::move(pItem)); + } +} + +void TemplateLocalView::reload() +{ + mpDocTemplates->Update(); + OUString sCurRegionName = getRegionItemName(mnCurRegionId); + Populate(); + mnCurRegionId = getRegionId(sCurRegionName); + + // Check if we are currently browsing a region or root folder + if (mnCurRegionId) + { + sal_uInt16 nRegionId = mnCurRegionId - 1; //Is offset by 1 + + for (auto const & pRegion : maRegions) + { + if (pRegion->mnRegionId == nRegionId) + { + showRegion(pRegion.get()); + break; + } + } + } + else + showAllTemplates(); + + //No items should be selected by default + deselectItems(); +} + +void TemplateLocalView::showAllTemplates() +{ + mnCurRegionId = 0; + + insertItems(maAllTemplates, false, true); + + maOpenRegionHdl.Call(nullptr); +} + +void TemplateLocalView::showRegion(TemplateContainerItem const *pItem) +{ + mnCurRegionId = pItem->mnRegionId+1; + + insertItems(pItem->maTemplates); + + maOpenRegionHdl.Call(nullptr); +} + +TemplateContainerItem* TemplateLocalView::getRegion(std::u16string_view rName) +{ + for (auto const & pRegion : maRegions) + if (pRegion->maTitle == rName) + return pRegion.get(); + + return nullptr; +} + +void TemplateLocalView::ContextMenuSelectHdl(std::u16string_view rIdent) +{ + if (rIdent == u"open") + maOpenTemplateHdl.Call(maSelectedItem); + else if (rIdent == u"edit") + maEditTemplateHdl.Call(maSelectedItem); + else if (rIdent == u"rename") + { + InputDialog aTitleEditDlg(GetDrawingArea(), SfxResId(STR_RENAME_TEMPLATE)); + OUString sOldTitle = maSelectedItem->getTitle(); + aTitleEditDlg.SetEntryText(sOldTitle); + aTitleEditDlg.HideHelpBtn(); + + auto aCurRegionItems = getFilteredItems([&](const TemplateItemProperties& rItem) { + return rItem.aRegionName == getRegionName(maSelectedItem->mnRegionId); + }); + OUString sTooltip(SfxResId(STR_TOOLTIP_ERROR_RENAME_TEMPLATE)); + sTooltip = sTooltip.replaceFirst("$2", getRegionName(maSelectedItem->mnRegionId)); + aTitleEditDlg.setCheckEntry([&](OUString sNewTitle) { + if (sNewTitle.isEmpty() || sNewTitle == sOldTitle) + return true; + for (const auto& rItem : aCurRegionItems) + { + if (rItem.aName == sNewTitle) + { + aTitleEditDlg.SetTooltip(sTooltip.replaceFirst("$1", sNewTitle)); + return false; + } + } + return true; + }); + if (!aTitleEditDlg.run()) + return; + OUString sNewTitle = comphelper::string::strip(aTitleEditDlg.GetEntryText(), ' '); + + if ( !sNewTitle.isEmpty() && sNewTitle != sOldTitle ) + { + maSelectedItem->setTitle(sNewTitle); + } + } + else if (rIdent == u"delete") + { + std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo, + SfxResId(STR_QMSG_SEL_TEMPLATE_DELETE))); + if (xQueryDlg->run() != RET_YES) + return; + + maDeleteTemplateHdl.Call(maSelectedItem); + reload(); + } + else if (rIdent == u"default") + maDefaultTemplateHdl.Call(maSelectedItem); +} + +sal_uInt16 TemplateLocalView::getRegionId(size_t pos) const +{ + assert(pos < maRegions.size()); + + return maRegions[pos]->mnId; +} + +sal_uInt16 TemplateLocalView::getRegionId(std::u16string_view sRegion) const +{ + for (auto const & pRegion : maRegions) + { + if (pRegion->maTitle == sRegion) + return pRegion->mnId; + } + + return 0; +} + +OUString TemplateLocalView::getRegionName(const sal_uInt16 nRegionId) const +{ + return mpDocTemplates->GetRegionName(nRegionId); +} + +OUString TemplateLocalView::getRegionItemName(const sal_uInt16 nItemId) const +{ + for (auto const & pRegion : maRegions) + { + if (pRegion->mnId == nItemId) + return pRegion->maTitle; + } + + return OUString(); +} + +std::vector<OUString> TemplateLocalView::getFolderNames() +{ + size_t n = maRegions.size(); + std::vector<OUString> ret(n); + + for (size_t i = 0; i < n; ++i) + ret[i] = maRegions[i]->maTitle; + + return ret; +} + +std::vector<TemplateItemProperties> +TemplateLocalView::getFilteredItems(const std::function<bool (const TemplateItemProperties&)> &rFunc) const +{ + std::vector<TemplateItemProperties> aItems; + + if (mnCurRegionId) + { + TemplateContainerItem *pFolderItem = maRegions[mnCurRegionId-1].get(); + + for (const TemplateItemProperties & rItemProps : pFolderItem->maTemplates) + { + if (rFunc(rItemProps)) + aItems.push_back(rItemProps); + } + } + else + { + for (auto const & pFolderItem : maRegions) + { + for (const TemplateItemProperties & rItemProps : pFolderItem->maTemplates) + { + if (rFunc(rItemProps)) + aItems.push_back(rItemProps); + } + } + } + + return aItems; +} + +sal_uInt16 TemplateLocalView::createRegion(const OUString &rName) +{ + sal_uInt16 nRegionId = mpDocTemplates->GetRegionCount(); // Next regionId + sal_uInt16 nItemId = maRegions.size() + 1; + + if (!mpDocTemplates->InsertDir(rName,nRegionId)) + return 0; + + // Insert to the region cache list and to the thumbnail item list + std::unique_ptr<TemplateContainerItem> pItem(new TemplateContainerItem( nItemId )); + pItem->mnRegionId = nRegionId; + pItem->maTitle = rName; + + maRegions.push_back(std::move(pItem)); + + return nItemId; +} + +bool TemplateLocalView::renameRegion(std::u16string_view rTitle, const OUString &rNewTitle) +{ + TemplateContainerItem *pRegion = getRegion(rTitle); + + if(pRegion) + { + sal_uInt16 nRegionId = pRegion->mnRegionId; + return mpDocTemplates->SetName( rNewTitle, nRegionId, USHRT_MAX/*nDocId*/ ); + } + return false; +} + +bool TemplateLocalView::removeRegion(const sal_uInt16 nItemId) +{ + sal_uInt16 nRegionId = USHRT_MAX; + + // Remove from the region cache list + for (auto pRegionIt = maRegions.begin(); pRegionIt != maRegions.end();) + { + if ( (*pRegionIt)->mnId == nItemId ) + { + if (!mpDocTemplates->Delete((*pRegionIt)->mnRegionId,USHRT_MAX)) + return false; + + nRegionId = (*pRegionIt)->mnRegionId; + + pRegionIt = maRegions.erase(pRegionIt); + } + else + { + // Synchronize regions cache ids with SfxDocumentTemplates + if (nRegionId != USHRT_MAX && (*pRegionIt)->mnRegionId > nRegionId) + --(*pRegionIt)->mnRegionId; + + ++pRegionIt; + } + } + + if (nRegionId == USHRT_MAX) + return false; + + // Synchronize view regions ids with SfxDocumentTemplates + for (auto const& region : maRegions) + { + if (region->mnRegionId > nRegionId) + --region->mnRegionId; + } + + return true; +} + +bool TemplateLocalView::removeTemplate (const sal_uInt16 nItemId, const sal_uInt16 nSrcItemId) +{ + for (auto const & pRegion : maRegions) + { + if (pRegion->mnId == nSrcItemId) + { + TemplateContainerItem *pItem = pRegion.get(); + auto pIter = std::find_if(pItem->maTemplates.begin(), pItem->maTemplates.end(), + [nItemId](const TemplateItemProperties& rTemplate) { return rTemplate.nId == nItemId; }); + if (pIter != pItem->maTemplates.end()) + { + if (!mpDocTemplates->Delete(pItem->mnRegionId,pIter->nDocId)) + return false; + + pIter = pItem->maTemplates.erase(pIter); + + if (pRegion->mnRegionId == mnCurRegionId-1) + { + RemoveItem(nItemId); + Invalidate(); + } + + // Update Doc Idx for all templates that follow + for (; pIter != pItem->maTemplates.end(); ++pIter) + pIter->nDocId = pIter->nDocId - 1; + } + + CalculateItemPositions(); + break; + } + } + + return true; +} + +void TemplateLocalView::moveTemplates(const std::set<const ThumbnailViewItem*, selection_cmp_fn> &rItems, + const sal_uInt16 nTargetItem) +{ + TemplateContainerItem *pTarget = nullptr; + TemplateContainerItem *pSrc = nullptr; + + for (auto const & pRegion : maRegions) + { + if (pRegion->mnId == nTargetItem) + pTarget = pRegion.get(); + } + + if (!pTarget) + return; + + bool refresh = false; + + sal_uInt16 nTargetRegion = pTarget->mnRegionId; + sal_uInt16 nTargetIdx = mpDocTemplates->GetCount(nTargetRegion); // Next Idx + std::vector<sal_uInt16> aItemIds; // List of moved items ids (also prevents the invalidation of rItems iterators when we remove them as we go) + + std::set<const ThumbnailViewItem*,selection_cmp_fn>::const_iterator aSelIter; + for ( aSelIter = rItems.begin(); aSelIter != rItems.end(); ++aSelIter, ++nTargetIdx ) + { + const TemplateViewItem *pViewItem = static_cast<const TemplateViewItem*>(*aSelIter); + sal_uInt16 nSrcRegionId = pViewItem->mnRegionId; + + for (auto const & pRegion : maRegions) + { + if (pRegion->mnRegionId == nSrcRegionId) + pSrc = pRegion.get(); + } + + if(pSrc) + { + bool bCopy = !mpDocTemplates->Move(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnDocId); + + if (bCopy) + { + OUString sQuery = SfxResId(STR_MSG_QUERY_COPY).replaceFirst("$1", pViewItem->maTitle).replaceFirst("$2", + getRegionName(nTargetRegion)); + std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo, sQuery)); + if (xQueryDlg->run() != RET_YES) + { + OUString sMsg(SfxResId(STR_MSG_ERROR_LOCAL_MOVE)); + sMsg = sMsg.replaceFirst("$1",getRegionName(nTargetRegion)); + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetDrawingArea(), + VclMessageType::Warning, VclButtonsType::Ok, sMsg.replaceFirst( "$2",pViewItem->maTitle))); + xBox->run(); + + return; //return if any single move operation fails + } + + if (!mpDocTemplates->Copy(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnDocId)) + { + continue; + } + } + + // move template to destination + + TemplateItemProperties aTemplateItem; + aTemplateItem.nId = nTargetIdx + 1; + aTemplateItem.nDocId = nTargetIdx; + aTemplateItem.nRegionId = nTargetRegion; + aTemplateItem.aName = pViewItem->maTitle; + aTemplateItem.aPath = mpDocTemplates->GetPath(nTargetRegion,nTargetIdx); + aTemplateItem.aRegionName = pViewItem->maHelpText; + aTemplateItem.aThumbnail = pViewItem->maPreview1; + + pTarget->maTemplates.push_back(aTemplateItem); + + if (!bCopy) + { + // remove template from region cached data + + std::vector<TemplateItemProperties>::iterator pPropIter; + for (pPropIter = pSrc->maTemplates.begin(); pPropIter != pSrc->maTemplates.end();) + { + if (pPropIter->nDocId == pViewItem->mnDocId) + { + pPropIter = pSrc->maTemplates.erase(pPropIter); + aItemIds.push_back(pViewItem->mnDocId + 1);//mnid + } + else + { + // Keep region document id synchronized with SfxDocumentTemplates + if (pPropIter->nDocId > pViewItem->mnDocId) + --pPropIter->nDocId; + + ++pPropIter; + } + } + + // Keep view document id synchronized with SfxDocumentTemplates + for (auto const& item : mItemList) + { + auto pTemplateViewItem = static_cast<TemplateViewItem*>(item.get()); + if (pTemplateViewItem->mnDocId > pViewItem->mnDocId) + --pTemplateViewItem->mnDocId; + } + } + } + + refresh = true; + } + + // Remove items from the current view + for (auto const& itemId : aItemIds) + RemoveItem(itemId); + + if (refresh) + { + CalculateItemPositions(); + Invalidate(); + } +} + +bool TemplateLocalView::copyFrom (TemplateContainerItem *pItem, const OUString &rPath) +{ + sal_uInt16 nId = 1; + sal_uInt16 nDocId = 0; + sal_uInt16 nRegionId = pItem->mnRegionId; + OUString aPath(rPath); + + if (!pItem->maTemplates.empty()) + { + nId = pItem->maTemplates.back().nId+1; + nDocId = pItem->maTemplates.back().nDocId+1; + } + + if (mpDocTemplates->CopyFrom(nRegionId,nDocId,aPath)) + { + TemplateItemProperties aTemplate; + aTemplate.nId = nId; + aTemplate.nDocId = nDocId; + aTemplate.nRegionId = nRegionId; + aTemplate.aName = aPath; + aTemplate.aThumbnail = TemplateLocalView::fetchThumbnail(rPath, + TEMPLATE_THUMBNAIL_MAX_WIDTH, + TEMPLATE_THUMBNAIL_MAX_HEIGHT); + aTemplate.aPath = rPath; + aTemplate.aRegionName = getRegionName(nRegionId); + + pItem->maTemplates.push_back(aTemplate); + + CalculateItemPositions(); + + return true; + } + + return false; +} + +bool TemplateLocalView::exportTo(const sal_uInt16 nItemId, const sal_uInt16 nRegionItemId, std::u16string_view rName) +{ + for (auto const & pRegItem : maRegions) + { + if (pRegItem->mnId == nRegionItemId) + { + for (auto const& elem : pRegItem->maTemplates) + { + if (elem.nId == nItemId) + { + return mpDocTemplates->CopyTo(pRegItem->mnRegionId,elem.nDocId,rName); + } + } + + break; + } + } + + return false; +} + +bool TemplateLocalView::renameItem(ThumbnailViewItem* pItem, const OUString& sNewTitle) +{ + sal_uInt16 nRegionId = 0; + sal_uInt16 nDocId = USHRT_MAX; + TemplateViewItem* pDocItem = dynamic_cast<TemplateViewItem*>( pItem ); + + if ( pDocItem ) + { + nRegionId = pDocItem->mnRegionId; + nDocId = pDocItem->mnDocId; + } + + bool bRes = mpDocTemplates->SetName( sNewTitle, nRegionId, nDocId ); + if(bRes) + { + for (auto & pRegion : maRegions) + { + if (pRegion->mnId == nRegionId + 1 ) + { + for(auto & aTemplate : pRegion->maTemplates) + { + if(aTemplate.nId == nDocId + 1) + { + aTemplate.aName = sNewTitle; + break; + } + } + break; + } + } + OUString sRegionName; + for (auto & aTemplate : maAllTemplates) + { + if (aTemplate.nRegionId == nRegionId && aTemplate.nDocId == nDocId) + { + aTemplate.aName = sNewTitle; + sRegionName = aTemplate.aRegionName; + break; + } + } + + OUString sHelpText = SfxResId(STR_TEMPLATE_TOOLTIP); + sHelpText = (sHelpText.replaceFirst("$1", sNewTitle)).replaceFirst("$2", sRegionName); + pItem->setHelpText(sHelpText); + pItem->maTitle = sNewTitle; + } + return bRes; +} + +void TemplateLocalView::insertItems(const std::vector<TemplateItemProperties> &rTemplates, bool isRegionSelected, bool bShowCategoryInTooltip) +{ + std::vector<std::unique_ptr<ThumbnailViewItem>> aItems(rTemplates.size()); + for (size_t i = 0, n = rTemplates.size(); i < n; ++i ) + { + const TemplateItemProperties *pCur = &rTemplates[i]; + + std::unique_ptr<TemplateViewItem> pChild; + if(isRegionSelected) + pChild.reset(new TemplateViewItem(*this, pCur->nId)); + else + pChild.reset(new TemplateViewItem(*this, i+1)); + + pChild->mnDocId = pCur->nDocId; + pChild->mnRegionId = pCur->nRegionId; + pChild->maTitle = pCur->aName; + pChild->setPath(pCur->aPath); + + if(!bShowCategoryInTooltip) + pChild->setHelpText(pCur->aName); + else + { + OUString sHelpText = SfxResId(STR_TEMPLATE_TOOLTIP); + sHelpText = (sHelpText.replaceFirst("$1", pCur->aName)).replaceFirst("$2", pCur->aRegionName); + pChild->setHelpText(sHelpText); + } + + pChild->maPreview1 = pCur->aThumbnail; + + if(IsDefaultTemplate(pCur->aPath)) + pChild->showDefaultIcon(true); + + if ( pCur->aThumbnail.IsEmpty() ) + { + // Use the default thumbnail if we have nothing else + pChild->maPreview1 = TemplateLocalView::getDefaultThumbnail(pCur->aPath); + } + + aItems[i] = std::move(pChild); + } + + updateItems(std::move(aItems)); +} + +bool TemplateLocalView::MouseButtonDown( const MouseEvent& rMEvt ) +{ + GrabFocus(); + return ThumbnailView::MouseButtonDown(rMEvt); +} + +bool TemplateLocalView::Command(const CommandEvent& rCEvt) +{ + if (rCEvt.GetCommand() != CommandEventId::ContextMenu) + return CustomWidgetController::Command(rCEvt); + + if (rCEvt.IsMouseEvent()) + { + size_t nPos = ImplGetItem(rCEvt.GetMousePosPixel()); + Point aPosition(rCEvt.GetMousePosPixel()); + maPosition = aPosition; + ThumbnailViewItem* pItem = ImplGetItem(nPos); + const TemplateViewItem *pViewItem = dynamic_cast<const TemplateViewItem*>(pItem); + + if(pViewItem) + { + if(!pItem->isSelected()) + { + deselectItems(); + pItem->setSelection(true); + maItemStateHdl.Call(pItem); + } + maSelectedItem = dynamic_cast<TemplateViewItem*>(pItem); + maCreateContextMenuHdl.Call(pItem); + } + } + else + { + for (ThumbnailViewItem* pItem : mFilteredItemList) + { + if (pItem->isSelected()) + { + tools::Rectangle aRect = pItem->getDrawArea(); + maPosition = aRect.Center(); + maSelectedItem = dynamic_cast<TemplateViewItem*>(pItem); + maCreateContextMenuHdl.Call(pItem); + break; + } + } + } + return true; +} + +bool TemplateLocalView::KeyInput( const KeyEvent& rKEvt ) +{ + vcl::KeyCode aKeyCode = rKEvt.GetKeyCode(); + + if(aKeyCode == ( KEY_MOD1 | KEY_A ) ) + { + for (ThumbnailViewItem* pItem : mFilteredItemList) + { + if (!pItem->isSelected()) + { + pItem->setSelection(true); + maItemStateHdl.Call(pItem); + } + } + + if (IsReallyVisible() && IsUpdateMode()) + Invalidate(); + return true; + } + else if( aKeyCode == KEY_DELETE && !mFilteredItemList.empty()) + { + std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo, + SfxResId(STR_QMSG_SEL_TEMPLATE_DELETE))); + if (xQueryDlg->run() != RET_YES) + return true; + + //copy to avoid changing filtered item list during deletion + ThumbnailValueItemList mFilteredItemListCopy = mFilteredItemList; + + for (ThumbnailViewItem* pItem : mFilteredItemListCopy) + { + if (pItem->isSelected()) + { + maDeleteTemplateHdl.Call(pItem); + } + } + reload(); + } + + return ThumbnailView::KeyInput(rKEvt); +} + +void TemplateLocalView::setOpenRegionHdl(const Link<void*,void> &rLink) +{ + maOpenRegionHdl = rLink; +} + +void TemplateLocalView::setCreateContextMenuHdl(const Link<ThumbnailViewItem*,void> &rLink) +{ + maCreateContextMenuHdl = rLink; +} + +void TemplateLocalView::setOpenTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink) +{ + maOpenTemplateHdl = rLink; +} + +void TemplateLocalView::setEditTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink) +{ + maEditTemplateHdl = rLink; +} + +void TemplateLocalView::setDeleteTemplateHdl(const Link<void*,void> &rLink) +{ + maDeleteTemplateHdl = rLink; +} + +void TemplateLocalView::setDefaultTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink) +{ + maDefaultTemplateHdl = rLink; +} + +void TemplateLocalView::setMoveTemplateHdl(const Link<void*,void> &rLink) +{ + maMoveTemplateHdl = rLink; +} + +void TemplateLocalView::setExportTemplateHdl(const Link<void*,void> &rLink) +{ + maExportTemplateHdl = rLink; +} + +BitmapEx TemplateLocalView::scaleImg (const BitmapEx &rImg, tools::Long width, tools::Long height) +{ + BitmapEx aImg = rImg; + + if (!rImg.IsEmpty()) + { + Size aSize = rImg.GetSizePixel(); + + if (aSize.Width() == 0) + aSize.setWidth( 1 ); + + if (aSize.Height() == 0) + aSize.setHeight( 1 ); + + // make the picture fit the given width/height constraints + double nRatio = std::min(double(width)/double(aSize.Width()), double(height)/double(aSize.Height())); + + aImg.Scale(nRatio, nRatio); + } + + return aImg; +} + +bool TemplateLocalView::IsDefaultTemplate(const OUString& rPath) +{ + SvtModuleOptions aModOpt; + const css::uno::Sequence<OUString> &aServiceNames = aModOpt.GetAllServiceNames(); + + return std::any_of(aServiceNames.begin(), aServiceNames.end(), [&rPath](const OUString& rName) { + return SfxObjectFactory::GetStandardTemplate(rName).match(rPath); }); +} + +void TemplateLocalView::RemoveDefaultTemplateIcon(std::u16string_view rPath) +{ + for (const std::unique_ptr<ThumbnailViewItem>& pItem : mItemList) + { + TemplateViewItem* pViewItem = dynamic_cast<TemplateViewItem*>(pItem.get()); + if (pViewItem && pViewItem->getPath().match(rPath)) + { + pViewItem->showDefaultIcon(false); + Invalidate(); + return; + } + } +} + +BitmapEx TemplateLocalView::getDefaultThumbnail( std::u16string_view rPath ) +{ + BitmapEx aImg; + INetURLObject aUrl(rPath); + OUString aExt = aUrl.getExtension(); + + if ( ViewFilter_Application::isFilteredExtension( FILTER_APPLICATION::WRITER, aExt) ) + aImg = BitmapEx(SFX_THUMBNAIL_TEXT); + else if ( ViewFilter_Application::isFilteredExtension( FILTER_APPLICATION::CALC, aExt) ) + aImg = BitmapEx(SFX_THUMBNAIL_SHEET); + else if ( ViewFilter_Application::isFilteredExtension( FILTER_APPLICATION::IMPRESS, aExt) ) + aImg = BitmapEx(SFX_THUMBNAIL_PRESENTATION); + else if ( ViewFilter_Application::isFilteredExtension( FILTER_APPLICATION::DRAW, aExt) ) + aImg = BitmapEx(SFX_THUMBNAIL_DRAWING); + + return aImg; +} + +BitmapEx TemplateLocalView::fetchThumbnail (const OUString &msURL, tools::Long width, tools::Long height) +{ + return TemplateLocalView::scaleImg(ThumbnailView::readThumbnail(msURL), width, height); +} + +void TemplateLocalView::OnItemDblClicked (ThumbnailViewItem *pItem) +{ + TemplateViewItem* pViewItem = dynamic_cast<TemplateViewItem*>(pItem); + + if( pViewItem ) + maOpenTemplateHdl.Call(pViewItem); +} + +bool TemplateLocalView::IsInternalTemplate(const OUString& rPath) +{ + uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + css::uno::Reference< css::util::XPathSettings > xPathSettings = css::util::thePathSettings::get(xContext); + uno::Sequence<OUString> aInternalTemplateDirs; + uno::Any aAny = xPathSettings->getPropertyValue("Template_internal"); + aAny >>= aInternalTemplateDirs; + SfxURLRelocator_Impl aRelocator(xContext); + for (OUString& rInternalTemplateDir : asNonConstRange(aInternalTemplateDirs)) + { + aRelocator.makeRelocatableURL(rInternalTemplateDir); + aRelocator.makeAbsoluteURL(rInternalTemplateDir); + if(::utl::UCBContentHelper::IsSubPath(rInternalTemplateDir, rPath)) + return true; + } + return false; +} + +bool TemplateLocalView::IsBuiltInRegion(const OUString& rRegionName) +{ + bool isBuiltInCategory = false; + auto aGroupNames = DocTemplLocaleHelper::GetBuiltInGroupNames(); + isBuiltInCategory = std::find(aGroupNames.begin(), aGroupNames.end(), + rRegionName) != aGroupNames.end(); + if(isBuiltInCategory) + return true; + //check if it contains any internal template + for(const auto& rItem : maRegions) + { + if(rItem->maTitle == rRegionName) + { + for(const auto& rTemplateItem : rItem->maTemplates) + { + if(IsInternalTemplate(rTemplateItem.aPath)) + return true; + } + break; + } + } + return false; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |