Files
core/svx/source/gallery2/galmisc.cxx
Oliver Specht c4aa95310d tdf#160267 Fix SVG and add PNG format from the clipboard
Since 6c04b8356c SVG was added
to the supported clipboard formats but it did not work.
SVG support is now fixed and PNG format is added in the gallery.

Change-Id: Ic9cb2eebfc37bd38605dfaa3a1c353a7532af357
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165908
Tested-by: Jenkins
Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de>
2024-11-19 01:14:11 +01:00

560 lines
16 KiB
C++

/* -*- 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/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <sal/config.h>
#include <sot/storage.hxx>
#include <unotools/streamwrap.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/string.hxx>
#include <ucbhelper/content.hxx>
#include <com/sun/star/ucb/ContentCreationException.hpp>
#include <tools/urlobj.hxx>
#include <vcl/graphicfilter.hxx>
#include <svl/itempool.hxx>
#include <sfx2/docfile.hxx>
#include <vcl/svapp.hxx>
#include <vcl/window.hxx>
#include <svx/svdpage.hxx>
#include <svx/dialmgr.hxx>
#include <svx/svdograf.hxx>
#include <svx/fmmodel.hxx>
#include <svx/unomodel.hxx>
#include "codec.hxx"
#include <svx/strings.hrc>
#include <svx/galtheme.hxx>
#include <svx/galmisc.hxx>
#include <osl/diagnose.h>
#include <com/sun/star/awt/XProgressMonitor.hpp>
#include <com/sun/star/ucb/TransferInfo.hpp>
#include <com/sun/star/ucb/NameClash.hpp>
#include <memory>
using namespace ::com::sun::star;
GalleryGraphicImportRet GalleryGraphicImport( const INetURLObject& rURL, Graphic& rGraphic,
OUString& rFilterName )
{
GalleryGraphicImportRet nRet = GalleryGraphicImportRet::IMPORT_NONE;
SfxMedium aMedium( rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ );
aMedium.Download();
SvStream* pIStm = aMedium.GetInStream();
if( pIStm )
{
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
sal_uInt16 nFormat;
if( !rGraphicFilter.ImportGraphic( rGraphic, rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), *pIStm, GRFILTER_FORMAT_DONTKNOW, &nFormat ) )
{
rFilterName = rGraphicFilter.GetImportFormatName( nFormat );
nRet = GalleryGraphicImportRet::IMPORT_FILE;
}
}
return nRet;
}
bool GallerySvDrawImport( SvStream& rIStm, SdrModel& rModel )
{
sal_uInt32 nVersion;
bool bRet = false;
if( GalleryCodec::IsCoded( rIStm, nVersion ) )
{
SvMemoryStream aMemStm( 65535, 65535 );
GalleryCodec aCodec( rIStm );
aCodec.Read( aMemStm );
aMemStm.Seek( 0 );
if ( 2 == nVersion )
{
// recall to read as XML
bRet = GallerySvDrawImport( aMemStm, rModel );
}
}
else
{
// read as XML
uno::Reference< io::XInputStream > xInputStream( new utl::OInputStreamWrapper( rIStm ) );
rModel.GetItemPool().SetDefaultMetric( MapUnit::Map100thMM );
uno::Reference< lang::XComponent > xComponent;
bRet = SvxDrawingLayerImport( &rModel, xInputStream, xComponent, "com.sun.star.comp.Draw.XMLOasisImporter" );
if( !bRet || (rModel.GetPageCount() == 0) )
{
rIStm.Seek(0);
bRet = SvxDrawingLayerImport( &rModel, xInputStream, xComponent, "com.sun.star.comp.Draw.XMLImporter" );
}
}
return bRet;
}
bool CreateIMapGraphic( const FmFormModel& rModel, Graphic& rGraphic, ImageMap& rImageMap )
{
if (! rModel.GetPageCount() )
return false;
const SdrPage* pPage = rModel.GetPage( 0 );
const SdrObject* pObj = pPage->GetObj( 0 );
if ( pPage->GetObjCount() != 1 )
return false;
auto pGrafObj = dynamic_cast<const SdrGrafObj*>( pObj);
if (!pGrafObj)
return false;
bool bRet = false;
const sal_uInt16 nCount = pObj->GetUserDataCount();
// Exist in the user data an IMap information?
for ( sal_uInt16 i = 0; i < nCount; i++ )
{
const SdrObjUserData* pUserData = pObj->GetUserData( i );
if ( ( pUserData->GetInventor() == SdrInventor::SgaImap ) && ( pUserData->GetId() == ID_IMAPINFO ) )
{
rGraphic = pGrafObj->GetGraphic();
rImageMap = static_cast<const SgaIMapInfo*>( pUserData )->GetImageMap();
bRet = true;
break;
}
}
return bRet;
}
OUString GetReducedString( const INetURLObject& rURL, sal_Int32 nMaxLen )
{
OUString aReduced( rURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ) );
aReduced = aReduced.copy(aReduced.lastIndexOf('/')+1);
if( INetProtocol::PrivSoffice != rURL.GetProtocol() )
{
sal_Unicode aDelimiter;
const OUString aPath( rURL.getFSysPath( FSysStyle::Detect, &aDelimiter ) );
const OUString aName( aReduced );
if( aPath.getLength() > nMaxLen )
{
sal_Int32 nPathPrefixLen = nMaxLen - aName.getLength() - 4;
if (nPathPrefixLen >= 0)
{
aReduced = OUString::Concat(aPath.subView(0, nPathPrefixLen)) + "..."
+ OUStringChar(aDelimiter) + aName;
}
else
{
aReduced += "..." + OUStringChar(aDelimiter) + "..."
+ aName.subView( aName.getLength() - (nMaxLen - 7) );
}
}
else
aReduced = aPath;
}
return aReduced;
}
OUString GetSvDrawStreamNameFromURL( const INetURLObject& rSvDrawObjURL )
{
OUString aRet;
if( rSvDrawObjURL.GetProtocol() == INetProtocol::PrivSoffice &&
comphelper::string::getTokenCount(rSvDrawObjURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), '/') == 3 )
{
aRet = rSvDrawObjURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ).getToken( 2, '/' );
}
return aRet;
}
bool FileExists( const INetURLObject& rURL )
{
bool bRet = false;
if( rURL.GetProtocol() != INetProtocol::NotValid )
{
try
{
::ucbhelper::Content aCnt( rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), uno::Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
OUString aTitle;
aCnt.getPropertyValue(u"Title"_ustr) >>= aTitle;
bRet = ( !aTitle.isEmpty() );
}
catch( const ucb::ContentCreationException& )
{
}
catch( const uno::RuntimeException& )
{
}
catch( const uno::Exception& )
{
}
}
return bRet;
}
bool CreateDir( const INetURLObject& rURL )
{
bool bRet = FileExists( rURL );
if( !bRet )
{
try
{
uno::Reference< ucb::XCommandEnvironment > aCmdEnv;
INetURLObject aParentURL( rURL );
aParentURL.removeSegment();
::ucbhelper::Content aParent( aParentURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), aCmdEnv, comphelper::getProcessComponentContext() );
uno::Sequence< OUString > aProps{ u"Title"_ustr };
uno::Sequence< uno::Any > aValues{ uno::Any(rURL.GetLastName()) };
::ucbhelper::Content aContent( rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), aCmdEnv, comphelper::getProcessComponentContext() );
bRet = aParent.insertNewContent( u"application/vnd.sun.staroffice.fsys-folder"_ustr, aProps, aValues, aContent );
}
catch( const ucb::ContentCreationException& )
{
}
catch( const uno::RuntimeException& )
{
}
catch( const uno::Exception& )
{
}
}
return bRet;
}
bool CopyFile( const INetURLObject& rSrcURL, const INetURLObject& rDstURL )
{
bool bRet = false;
try
{
::ucbhelper::Content aDestPath( rDstURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), uno::Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
aDestPath.executeCommand( u"transfer"_ustr,
uno::Any( ucb::TransferInfo( false, rSrcURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
rDstURL.GetLastName(), ucb::NameClash::OVERWRITE ) ) );
bRet = true;
}
catch( const ucb::ContentCreationException& )
{
}
catch( const uno::RuntimeException& )
{
}
catch( const uno::Exception& )
{
}
return bRet;
}
bool KillFile( const INetURLObject& rURL )
{
bool bRet = FileExists( rURL );
if( bRet )
{
try
{
::ucbhelper::Content aCnt( rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), uno::Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
aCnt.executeCommand( u"delete"_ustr, uno::Any( true ) );
}
catch( const ucb::ContentCreationException& )
{
bRet = false;
}
catch( const uno::RuntimeException& )
{
bRet = false;
}
catch( const uno::Exception& )
{
bRet = false;
}
}
return bRet;
}
GalleryProgress::GalleryProgress( const GraphicFilter* pFilter )
{
uno::Reference< lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
uno::Reference< awt::XProgressMonitor > xMonitor( xMgr->createInstance( u"com.sun.star.awt.XProgressMonitor"_ustr ),
uno::UNO_QUERY );
if ( !xMonitor.is() )
return;
mxProgressBar = xMonitor;
OUString aProgressText;
if( pFilter )
{
aProgressText = SvxResId(RID_SVXSTR_GALLERY_FILTER);
// pFilter->SetUpdatePercentHdl( LINK( this, GalleryProgress, Update ) ); // sj: progress wasn't working up from SO7 at all
// // so I am removing this. The gallery progress should
// // be changed to use the XStatusIndicator instead of XProgressMonitor
}
else
aProgressText = "Gallery";
xMonitor->addText( u"Gallery"_ustr, aProgressText, false ) ;
mxProgressBar->setRange( 0, GALLERY_PROGRESS_RANGE );
}
GalleryProgress::~GalleryProgress()
{
}
void GalleryProgress::Update( sal_Int32 nVal, sal_Int32 nMaxVal )
{
if( mxProgressBar.is() && nMaxVal )
mxProgressBar->setValue( std::min<sal_Int32>( static_cast<double>(nVal) / nMaxVal * GALLERY_PROGRESS_RANGE,
GALLERY_PROGRESS_RANGE ) );
}
GalleryTransferable::GalleryTransferable( GalleryTheme* pTheme, sal_uInt32 nObjectPos, bool bLazy ) :
mpTheme( pTheme ),
meObjectKind( pTheme ? mpTheme->GetObjectKind(nObjectPos) : SgaObjKind::NONE),
mnObjectPos( nObjectPos )
{
InitData( bLazy );
}
void GalleryTransferable::SelectObject(sal_uInt32 nObjectPos)
{
if (nObjectPos == mnObjectPos)
return;
ClearFormats();
mnObjectPos = nObjectPos;
meObjectKind = mpTheme ? mpTheme->GetObjectKind(mnObjectPos) : SgaObjKind::NONE;
ObjectReleased();
InitData(true);
}
GalleryTransferable::~GalleryTransferable()
{
}
void GalleryTransferable::InitData( bool bLazy )
{
switch( meObjectKind )
{
case SgaObjKind::SvDraw:
{
if( !bLazy )
{
if( !mpGraphicObject )
{
Graphic aGraphic;
if (mpTheme && mpTheme->GetGraphic(mnObjectPos, aGraphic))
mpGraphicObject.reset(new GraphicObject( std::move(aGraphic) ));
}
if( !mxModelStream )
{
mxModelStream = SotTempStream::Create( u""_ustr );
mxModelStream->SetBufferSize( 16348 );
if (!mpTheme || !mpTheme->GetModelStream(mnObjectPos, *mxModelStream))
mxModelStream.reset();
else
mxModelStream->Seek( 0 );
}
}
}
break;
case SgaObjKind::Animation:
case SgaObjKind::Bitmap:
case SgaObjKind::Inet:
case SgaObjKind::Sound:
{
if( !mpURL )
{
mpURL.reset(new INetURLObject);
if (!mpTheme || !mpTheme->GetURL(mnObjectPos, *mpURL))
{
mpURL.reset();
}
}
if( ( SgaObjKind::Sound != meObjectKind ) && !mpGraphicObject )
{
Graphic aGraphic;
if (mpTheme && mpTheme->GetGraphic(mnObjectPos, aGraphic))
mpGraphicObject.reset(new GraphicObject( std::move(aGraphic) ));
}
}
break;
default:
OSL_FAIL( "GalleryTransferable::GalleryTransferable: invalid object type" );
break;
}
}
void GalleryTransferable::AddSupportedFormats()
{
if( SgaObjKind::SvDraw == meObjectKind )
{
AddFormat( SotClipboardFormatId::DRAWING );
AddFormat( SotClipboardFormatId::SVXB );
AddFormat( SotClipboardFormatId::GDIMETAFILE );
AddFormat( SotClipboardFormatId::BITMAP );
}
else
{
if( mpURL )
AddFormat( SotClipboardFormatId::SIMPLE_FILE );
if( mpGraphicObject )
{
AddFormat( SotClipboardFormatId::SVXB );
if( mpGraphicObject->GetType() == GraphicType::GdiMetafile )
{
AddFormat( SotClipboardFormatId::GDIMETAFILE );
AddFormat( SotClipboardFormatId::BITMAP );
}
else
{
AddFormat( SotClipboardFormatId::BITMAP );
AddFormat( SotClipboardFormatId::GDIMETAFILE );
}
}
}
}
bool GalleryTransferable::GetData( const datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
{
SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );
bool bRet = false;
InitData( false );
if( ( SotClipboardFormatId::DRAWING == nFormat ) && ( SgaObjKind::SvDraw == meObjectKind ) )
{
bRet = ( mxModelStream && SetObject( mxModelStream.get(), 0, rFlavor ) );
}
else if( ( SotClipboardFormatId::SIMPLE_FILE == nFormat ) && mpURL )
{
bRet = SetString( mpURL->GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
}
else if( ( SotClipboardFormatId::SVXB == nFormat ) && mpGraphicObject )
{
bRet = SetGraphic( mpGraphicObject->GetGraphic() );
}
else if( ( SotClipboardFormatId::GDIMETAFILE == nFormat ) && mpGraphicObject )
{
bRet = SetGDIMetaFile( mpGraphicObject->GetGraphic().GetGDIMetaFile() );
}
else if( ( SotClipboardFormatId::BITMAP == nFormat || SotClipboardFormatId::PNG == nFormat)
&& mpGraphicObject )
{
bRet = SetBitmapEx( mpGraphicObject->GetGraphic().GetBitmapEx(), rFlavor );
}
return bRet;
}
bool GalleryTransferable::WriteObject( SvStream& rOStm, void* pUserObject,
sal_uInt32, const datatransfer::DataFlavor& )
{
bool bRet = false;
if( pUserObject )
{
rOStm.WriteStream( *static_cast< SotStorageStream* >( pUserObject ) );
bRet = ( rOStm.GetError() == ERRCODE_NONE );
}
return bRet;
}
void GalleryTransferable::DragFinished( sal_Int8 nDropAction )
{
if (mpTheme)
{
mpTheme->SetDragging( false );
mpTheme->SetDragPos( 0 );
}
if ( nDropAction )
{
vcl::Window *pFocusWindow = Application::GetFocusWindow();
if ( pFocusWindow )
pFocusWindow->GrabFocusToDocument();
}
}
void GalleryTransferable::ObjectReleased()
{
mxModelStream.reset();
mpGraphicObject.reset();
mpURL.reset();
}
bool GalleryTransferable::StartDrag()
{
INetURLObject aURL;
if (mpTheme && mpTheme->GetURL(mnObjectPos, aURL) && aURL.GetProtocol() != INetProtocol::NotValid)
{
mpTheme->SetDragging( true );
mpTheme->SetDragPos( mnObjectPos );
return false;
}
return true;
}
INetURLObject ImplGetURL(const GalleryObject* pObject)
{
INetURLObject aURL;
if (pObject)
aURL = *pObject->m_oStorageUrl;
return aURL;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */