1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "clickableimage.hxx"
21 #include <controlfeatureinterception.hxx>
22 #include <urltransformer.hxx>
23 #include <componenttools.hxx>
24 #include <com/sun/star/form/XSubmit.hpp>
25 #include <com/sun/star/frame/XDispatch.hpp>
26 #include <com/sun/star/frame/XDispatchProvider.hpp>
27 #include <com/sun/star/frame/FrameSearchFlag.hpp>
28 #include <com/sun/star/frame/XController.hpp>
29 #include <com/sun/star/frame/XFrame.hpp>
30 #include <com/sun/star/awt/ActionEvent.hpp>
31 #include <com/sun/star/graphic/XGraphic.hpp>
32 #include <com/sun/star/graphic/GraphicObject.hpp>
33 #include <com/sun/star/util/VetoException.hpp>
34 #include <tools/urlobj.hxx>
35 #include <tools/debug.hxx>
36 #include <comphelper/diagnose_ex.hxx>
37 #include <vcl/graph.hxx>
38 #include <vcl/svapp.hxx>
39 #include <sfx2/docfile.hxx>
40 #include <sfx2/objsh.hxx>
41 #include <osl/mutex.hxx>
42 #include <property.hxx>
43 #include <services.hxx>
44 #include <comphelper/interfacecontainer3.hxx>
45 #include <comphelper/property.hxx>
46 #include <comphelper/propertyvalue.hxx>
47 #include <comphelper/types.hxx>
48 #include <cppuhelper/exc_hlp.hxx>
49 #include <svtools/imageresourceaccess.hxx>
50 #include <unotools/securityoptions.hxx>
51 #define LOCAL_URL_PREFIX '#'
58 using namespace ::com::sun::star::uno
;
59 using namespace ::com::sun::star::sdb
;
60 using namespace ::com::sun::star::sdbc
;
61 using namespace ::com::sun::star::beans
;
62 using namespace ::com::sun::star::container
;
63 using namespace ::com::sun::star::form
;
64 using namespace ::com::sun::star::awt
;
65 using namespace ::com::sun::star::lang
;
66 using namespace ::com::sun::star::util
;
67 using namespace ::com::sun::star::frame
;
68 using namespace ::com::sun::star::form::submission
;
69 using namespace ::com::sun::star::graphic
;
70 using ::com::sun::star::awt::MouseEvent
;
71 using ::com::sun::star::task::XInteractionHandler
;
74 // OClickableImageBaseControl
77 Sequence
<Type
> OClickableImageBaseControl::_getTypes()
79 static Sequence
<Type
> const aTypes
=
80 concatSequences(OControl::_getTypes(), OClickableImageBaseControl_BASE::getTypes());
85 OClickableImageBaseControl::OClickableImageBaseControl(const Reference
<XComponentContext
>& _rxFactory
, const OUString
& _aService
)
86 :OControl(_rxFactory
, _aService
)
87 ,m_aSubmissionVetoListeners( m_aMutex
)
88 ,m_aFeatureInterception( _rxFactory
)
89 ,m_aApproveActionListeners( m_aMutex
)
90 ,m_aActionListeners( m_aMutex
)
95 OClickableImageBaseControl::~OClickableImageBaseControl()
97 if (!OComponentHelper::rBHelper
.bDisposed
)
106 Any SAL_CALL
OClickableImageBaseControl::queryAggregation(const Type
& _rType
)
108 Any aReturn
= OControl::queryAggregation(_rType
);
109 if (!aReturn
.hasValue())
110 aReturn
= OClickableImageBaseControl_BASE::queryInterface(_rType
);
114 // XApproveActionBroadcaster
116 void OClickableImageBaseControl::addApproveActionListener(
117 const Reference
<XApproveActionListener
>& l
)
119 m_aApproveActionListeners
.addInterface(l
);
123 void OClickableImageBaseControl::removeApproveActionListener(
124 const Reference
<XApproveActionListener
>& l
)
126 m_aApproveActionListeners
.removeInterface(l
);
130 void SAL_CALL
OClickableImageBaseControl::registerDispatchProviderInterceptor( const Reference
< XDispatchProviderInterceptor
>& _rxInterceptor
)
132 m_aFeatureInterception
.registerDispatchProviderInterceptor( _rxInterceptor
);
136 void SAL_CALL
OClickableImageBaseControl::releaseDispatchProviderInterceptor( const Reference
< XDispatchProviderInterceptor
>& _rxInterceptor
)
138 m_aFeatureInterception
.releaseDispatchProviderInterceptor( _rxInterceptor
);
143 void OClickableImageBaseControl::disposing()
145 EventObject
aEvent( static_cast< XWeak
* >( this ) );
146 m_aApproveActionListeners
.disposeAndClear( aEvent
);
147 m_aActionListeners
.disposeAndClear( aEvent
);
148 m_aSubmissionVetoListeners
.disposeAndClear( aEvent
);
149 m_aFeatureInterception
.dispose();
152 ::osl::MutexGuard
aGuard( m_aMutex
);
156 OControl::disposing();
160 OImageProducerThread_Impl
* OClickableImageBaseControl::getImageProducerThread()
162 if ( !m_pThread
.is() )
164 m_pThread
= new OImageProducerThread_Impl( this );
167 return m_pThread
.get();
171 bool OClickableImageBaseControl::approveAction( )
173 bool bCancelled
= false;
174 EventObject
aEvent( static_cast< XWeak
* >( this ) );
176 ::comphelper::OInterfaceIteratorHelper3
aIter( m_aApproveActionListeners
);
177 while( !bCancelled
&& aIter
.hasMoreElements() )
179 // Every approveAction method must be thread-safe!
180 if( !aIter
.next()->approveAction( aEvent
) )
188 // This method is also called from a thread and thus must be thread-safe.
189 void OClickableImageBaseControl::actionPerformed_Impl(bool bNotifyListener
, const MouseEvent
& rEvt
)
191 if( bNotifyListener
)
193 if ( !approveAction() )
197 // Whether the rest of the code is thread-safe, one can't tell. Therefore
198 // we do most of the work on a locked solar mutex.
199 Reference
<XPropertySet
> xSet
;
200 Reference
< XInterface
> xModelsParent
;
201 FormButtonType eButtonType
= FormButtonType_PUSH
;
203 SolarMutexGuard aGuard
;
206 Reference
<XFormComponent
> xComp(getModel(), UNO_QUERY
);
210 xModelsParent
= xComp
->getParent();
211 if (!xModelsParent
.is())
214 // Which button type?
215 xSet
.set(xComp
, css::uno::UNO_QUERY
);
218 xSet
->getPropertyValue(PROPERTY_BUTTONTYPE
) >>= eButtonType
;
223 case FormButtonType_RESET
:
225 // Reset methods must be thread-safe!
226 Reference
<XReset
> xReset(xModelsParent
, UNO_QUERY
);
234 case FormButtonType_SUBMIT
:
236 // if some outer component can provide an interaction handler, use it
237 Reference
< XInteractionHandler
> xHandler( m_aFeatureInterception
.queryDispatch( u
"private:/InteractionHandler"_ustr
), UNO_QUERY
);
240 implSubmit( rEvt
, xHandler
);
242 catch( const Exception
& )
249 case FormButtonType_URL
:
251 SolarMutexGuard aGuard
;
253 Reference
< XModel
> xModel
= getXModel(xModelsParent
);
259 Reference
< XController
> xController
= xModel
->getCurrentController();
260 if (!xController
.is())
263 Reference
< XFrame
> xFrame
= xController
->getFrame();
269 getString(xSet
->getPropertyValue(PROPERTY_TARGET_URL
));
271 if (!aURL
.Complete
.isEmpty() && (LOCAL_URL_PREFIX
== aURL
.Complete
[0]))
272 { // FIXME: The URL contains a local URL only. Since the URLTransformer does not handle this case correctly
273 // (it can't: it does not know the document URL), we have to take care for this ourself.
274 // The real solution would be to not allow such relative URLs (there is a rule that at runtime, all
275 // URLs have to be absolute), but for compatibility reasons this is no option.
276 // The more as the user does not want to see a local URL as "file://<path>/<document>#mark" if it
277 // could be "#mark" as well.
278 // If we someday say that this hack (yes, it's kind of a hack) is not sustainable anymore, the complete
279 // solution would be:
280 // * recognize URLs consisting of a mark only while _reading_ the document
281 // * for this, allow the INetURLObject (which at the moment is invoked when reading URLs) to
282 // transform such mark-only URLs into correct absolute URLs
283 // * at the UI, show only the mark
284 // * !!! recognize every SAVEAS on the document, so the absolute URL can be adjusted. This seems
285 // rather impossible !!!
286 aURL
.Mark
= aURL
.Complete
;
287 aURL
.Complete
= xModel
->getURL();
288 aURL
.Complete
+= aURL
.Mark
;
291 bool bDispatchUrlInternal
= false;
292 xSet
->getPropertyValue(PROPERTY_DISPATCHURLINTERNAL
) >>= bDispatchUrlInternal
;
293 if ( bDispatchUrlInternal
)
295 m_aFeatureInterception
.getTransformer().parseSmartWithProtocol( aURL
, INET_FILE_SCHEME
);
297 OUString aTargetFrame
;
298 xSet
->getPropertyValue(PROPERTY_TARGET_FRAME
) >>= aTargetFrame
;
300 Reference
< XDispatch
> xDisp
= Reference
< XDispatchProvider
> (xFrame
,UNO_QUERY_THROW
)->queryDispatch( aURL
, aTargetFrame
,
301 FrameSearchFlag::SELF
| FrameSearchFlag::PARENT
|
302 FrameSearchFlag::SIBLINGS
| FrameSearchFlag::CREATE
);
304 Sequence
<PropertyValue
> aArgs
{ comphelper::makePropertyValue(u
"Referer"_ustr
, xModel
->getURL()) };
307 xDisp
->dispatch( aURL
, aArgs
);
311 URL aHyperLink
= m_aFeatureInterception
.getTransformer().getStrictURL( u
".uno:OpenHyperlink"_ustr
);
313 Reference
< XDispatch
> xDisp
= Reference
< XDispatchProvider
> (xFrame
,UNO_QUERY_THROW
)->queryDispatch(aHyperLink
, OUString() , 0);
317 Sequence
<PropertyValue
> aProps
{
318 comphelper::makePropertyValue(u
"URL"_ustr
, aURL
.Complete
),
319 comphelper::makePropertyValue(
320 u
"FrameName"_ustr
, xSet
->getPropertyValue(PROPERTY_TARGET_FRAME
)),
321 comphelper::makePropertyValue(u
"Referer"_ustr
, xModel
->getURL())
324 xDisp
->dispatch( aHyperLink
, aProps
);
330 // notify the action listeners for a push button
331 ActionEvent
aEvt(static_cast<XWeak
*>(this), m_aActionCommand
);
332 m_aActionListeners
.notifyEach( &XActionListener::actionPerformed
, aEvt
);
338 void SAL_CALL
OClickableImageBaseControl::addSubmissionVetoListener( const Reference
< submission::XSubmissionVetoListener
>& listener
)
340 m_aSubmissionVetoListeners
.addInterface( listener
);
344 void SAL_CALL
OClickableImageBaseControl::removeSubmissionVetoListener( const Reference
< submission::XSubmissionVetoListener
>& listener
)
346 m_aSubmissionVetoListeners
.removeInterface( listener
);
350 void SAL_CALL
OClickableImageBaseControl::submitWithInteraction( const Reference
< XInteractionHandler
>& _rxHandler
)
352 implSubmit( MouseEvent(), _rxHandler
);
356 void SAL_CALL
OClickableImageBaseControl::submit( )
358 implSubmit( MouseEvent(), nullptr );
362 Sequence
< OUString
> SAL_CALL
OClickableImageBaseControl::getSupportedServiceNames( )
364 Sequence
< OUString
> aSupported
= OControl::getSupportedServiceNames();
365 aSupported
.realloc( aSupported
.getLength() + 1 );
367 OUString
* pArray
= aSupported
.getArray();
368 pArray
[ aSupported
.getLength() - 1 ] = FRM_SUN_CONTROL_SUBMITBUTTON
;
374 void OClickableImageBaseControl::implSubmit( const MouseEvent
& _rEvent
, const Reference
< XInteractionHandler
>& _rxHandler
)
378 // allow the veto listeners to join the game
379 m_aSubmissionVetoListeners
.notifyEach( &XSubmissionVetoListener::submitting
, EventObject( *this ) );
381 // see whether there's an "submit interceptor" set at our model
382 Reference
< submission::XSubmissionSupplier
> xSubmissionSupp( getModel(), UNO_QUERY
);
383 Reference
< XSubmission
> xSubmission
;
384 if ( xSubmissionSupp
.is() )
385 xSubmission
= xSubmissionSupp
->getSubmission();
387 if ( xSubmission
.is() )
389 if ( !_rxHandler
.is() )
390 xSubmission
->submit();
392 xSubmission
->submitWithInteraction( _rxHandler
);
396 // no "interceptor" -> ordinary (old-way) submission
397 Reference
< XChild
> xChild( getModel(), UNO_QUERY
);
398 Reference
< XSubmit
> xParentSubmission
;
400 xParentSubmission
.set(xChild
->getParent(), css::uno::UNO_QUERY
);
401 if ( xParentSubmission
.is() )
402 xParentSubmission
->submit( this, _rEvent
);
405 catch( const VetoException
& )
410 catch( const RuntimeException
& )
415 catch( const WrappedTargetException
& )
420 catch( const Exception
& )
422 css::uno::Any anyEx
= cppu::getCaughtException();
423 TOOLS_WARN_EXCEPTION( "forms.component", "OClickableImageBaseControl::implSubmit: caught an unknown exception!" );
424 throw WrappedTargetException( OUString(), *this, anyEx
);
429 // OClickableImageBaseModel
432 Sequence
<Type
> OClickableImageBaseModel::_getTypes()
434 return concatSequences(
435 OControlModel::_getTypes(),
436 OClickableImageBaseModel_Base::getTypes()
441 OClickableImageBaseModel::OClickableImageBaseModel( const Reference
< XComponentContext
>& _rxFactory
, const OUString
& _rUnoControlModelTypeName
,
442 const OUString
& rDefault
)
443 :OControlModel( _rxFactory
, _rUnoControlModelTypeName
, rDefault
)
444 ,OPropertyChangeListener()
445 ,m_bDispatchUrlInternal(false)
446 ,m_bProdStarted(false)
449 m_eButtonType
= FormButtonType_PUSH
;
453 OClickableImageBaseModel::OClickableImageBaseModel( const OClickableImageBaseModel
* _pOriginal
, const Reference
<XComponentContext
>& _rxFactory
)
454 :OControlModel( _pOriginal
, _rxFactory
)
455 ,OPropertyChangeListener()
456 ,m_xGraphicObject( _pOriginal
->m_xGraphicObject
)
457 ,m_bDispatchUrlInternal(false)
458 ,m_bProdStarted( false )
463 m_eButtonType
= _pOriginal
->m_eButtonType
;
464 m_sTargetURL
= _pOriginal
->m_sTargetURL
;
465 m_sTargetFrame
= _pOriginal
->m_sTargetFrame
;
466 m_bDispatchUrlInternal
= _pOriginal
->m_bDispatchUrlInternal
;
470 void OClickableImageBaseModel::implInitializeImageURL( )
472 osl_atomic_increment( &m_refCount
);
474 // simulate a propertyChanged event for the ImageURL
476 getFastPropertyValue( aImageURL
, PROPERTY_ID_IMAGE_URL
);
477 _propertyChanged( PropertyChangeEvent( *this, PROPERTY_IMAGE_URL
, false, PROPERTY_ID_IMAGE_URL
, Any( ), aImageURL
) );
479 osl_atomic_decrement( &m_refCount
);
483 void OClickableImageBaseModel::implConstruct()
485 m_xProducer
= new ImageProducer
;
486 m_xProducer
->SetDoneHdl( LINK( this, OClickableImageBaseModel
, OnImageImportDone
) );
487 osl_atomic_increment( &m_refCount
);
489 if ( m_xAggregateSet
.is() )
491 rtl::Reference
<OPropertyChangeMultiplexer
> pMultiplexer
= new OPropertyChangeMultiplexer( this, m_xAggregateSet
);
492 pMultiplexer
->addProperty( PROPERTY_IMAGE_URL
);
495 osl_atomic_decrement(&m_refCount
);
499 OClickableImageBaseModel::~OClickableImageBaseModel()
501 if (!OComponentHelper::rBHelper
.bDisposed
)
506 DBG_ASSERT(m_pMedium
== nullptr, "OClickableImageBaseModel::~OClickableImageBaseModel : leaving a memory leak ...");
507 // This should be cleaned up at least in the dispose
513 void SAL_CALL
OClickableImageBaseModel::addConsumer( const Reference
< XImageConsumer
>& _rxConsumer
)
515 ImageModelMethodGuard
aGuard( *this );
516 GetImageProducer()->addConsumer( _rxConsumer
);
520 void SAL_CALL
OClickableImageBaseModel::removeConsumer( const Reference
< XImageConsumer
>& _rxConsumer
)
522 ImageModelMethodGuard
aGuard( *this );
523 GetImageProducer()->removeConsumer( _rxConsumer
);
527 void SAL_CALL
OClickableImageBaseModel::startProduction( )
529 ImageModelMethodGuard
aGuard( *this );
530 GetImageProducer()->startProduction();
534 Reference
< submission::XSubmission
> SAL_CALL
OClickableImageBaseModel::getSubmission()
536 return m_xSubmissionDelegate
;
540 void SAL_CALL
OClickableImageBaseModel::setSubmission( const Reference
< submission::XSubmission
>& _submission
)
542 m_xSubmissionDelegate
= _submission
;
546 Sequence
< OUString
> SAL_CALL
OClickableImageBaseModel::getSupportedServiceNames( )
548 Sequence
< OUString
> aSupported
= OControlModel::getSupportedServiceNames();
549 aSupported
.realloc( aSupported
.getLength() + 1 );
551 OUString
* pArray
= aSupported
.getArray();
552 pArray
[ aSupported
.getLength() - 1 ] = FRM_SUN_COMPONENT_SUBMITBUTTON
;
559 void OClickableImageBaseModel::disposing()
561 OControlModel::disposing();
567 Any SAL_CALL
OClickableImageBaseModel::queryAggregation(const Type
& _rType
)
570 // we definitely want to "override" the XImageProducer interface of our aggregate,
571 // thus check OClickableImageBaseModel_Base (which provides this) first
572 Any aReturn
= OClickableImageBaseModel_Base::queryInterface( _rType
);
574 // BUT: _don't_ let it feel responsible for the XTypeProvider interface
575 // (as this is implemented by our base class in the proper way)
576 if ( _rType
.equals( cppu::UnoType
<XTypeProvider
>::get() )
577 || !aReturn
.hasValue()
579 aReturn
= OControlModel::queryAggregation( _rType
);
585 void OClickableImageBaseModel::getFastPropertyValue(Any
& rValue
, sal_Int32 nHandle
) const
589 case PROPERTY_ID_BUTTONTYPE
: rValue
<<= m_eButtonType
; break;
590 case PROPERTY_ID_TARGET_URL
: rValue
<<= m_sTargetURL
; break;
591 case PROPERTY_ID_TARGET_FRAME
: rValue
<<= m_sTargetFrame
; break;
592 case PROPERTY_ID_DISPATCHURLINTERNAL
: rValue
<<= m_bDispatchUrlInternal
; break;
594 OControlModel::getFastPropertyValue(rValue
, nHandle
);
599 void OClickableImageBaseModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
, const Any
& rValue
)
603 case PROPERTY_ID_BUTTONTYPE
:
604 DBG_ASSERT(rValue
.has
<FormButtonType
>(), "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
605 rValue
>>= m_eButtonType
;
608 case PROPERTY_ID_TARGET_URL
:
609 DBG_ASSERT(rValue
.getValueTypeClass() == TypeClass_STRING
, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
610 rValue
>>= m_sTargetURL
;
613 case PROPERTY_ID_TARGET_FRAME
:
614 DBG_ASSERT(rValue
.getValueTypeClass() == TypeClass_STRING
, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
615 rValue
>>= m_sTargetFrame
;
618 case PROPERTY_ID_DISPATCHURLINTERNAL
:
619 DBG_ASSERT(rValue
.getValueTypeClass() == TypeClass_BOOLEAN
, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
620 rValue
>>= m_bDispatchUrlInternal
;
624 OControlModel::setFastPropertyValue_NoBroadcast(nHandle
, rValue
);
629 sal_Bool
OClickableImageBaseModel::convertFastPropertyValue(Any
& rConvertedValue
, Any
& rOldValue
, sal_Int32 nHandle
, const Any
& rValue
)
633 case PROPERTY_ID_BUTTONTYPE
:
634 return tryPropertyValueEnum( rConvertedValue
, rOldValue
, rValue
, m_eButtonType
);
636 case PROPERTY_ID_TARGET_URL
:
637 return tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_sTargetURL
);
639 case PROPERTY_ID_TARGET_FRAME
:
640 return tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_sTargetFrame
);
642 case PROPERTY_ID_DISPATCHURLINTERNAL
:
643 return tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_bDispatchUrlInternal
);
646 return OControlModel::convertFastPropertyValue(rConvertedValue
, rOldValue
, nHandle
, rValue
);
651 void OClickableImageBaseModel::StartProduction()
653 ImageProducer
*pImgProd
= GetImageProducer();
656 getPropertyValue(u
"ImageURL"_ustr
) >>= sURL
;
659 if ( ::svt::GraphicAccess::isSupportedURL( sURL
) )
660 pImgProd
->SetImage( sURL
);
662 // caution: the medium may be NULL if somebody gave us an invalid URL to work with
663 pImgProd
->SetImage(OUString());
666 if (m_pMedium
->GetErrorCode()==ERRCODE_NONE
)
668 SvStream
* pStream
= m_pMedium
->GetInStream();
670 pImgProd
->SetImage(*pStream
);
671 pImgProd
->startProduction();
672 m_bProdStarted
= true;
676 pImgProd
->SetImage(OUString());
681 SfxObjectShell
* OClickableImageBaseModel::GetObjectShell()
683 // Find the XModel to get to the Object shell or at least the
685 // There's only a Model if we load HTML documents and the URL is
686 // changed in a document that is already loaded. There's no way
687 // we can get to the Model during loading.
688 Reference
< XModel
> xModel
;
689 css::uno::Reference
<css::uno::XInterface
> xIfc( *this );
690 while( !xModel
.is() && xIfc
.is() )
692 Reference
<XChild
> xChild( xIfc
, UNO_QUERY
);
693 xIfc
= xChild
->getParent();
694 xModel
.set(xIfc
, css::uno::UNO_QUERY
);
697 // Search for the Object shell by iterating over all Object shells
698 // and comparing their XModel to ours.
699 // As an optimization, we try the current Object shell first.
700 SfxObjectShell
*pObjSh
= nullptr;
704 SfxObjectShell
*pTestObjSh
= SfxObjectShell::Current();
707 Reference
< XModel
> xTestModel
= pTestObjSh
->GetModel();
708 if( xTestModel
== xModel
)
713 pTestObjSh
= SfxObjectShell::GetFirst();
714 while( !pObjSh
&& pTestObjSh
)
716 Reference
< XModel
> xTestModel
= pTestObjSh
->GetModel();
717 if( xTestModel
== xModel
)
720 pTestObjSh
= SfxObjectShell::GetNext( *pTestObjSh
);
728 void OClickableImageBaseModel::SetURL( const OUString
& rURL
)
730 if (m_pMedium
|| rURL
.isEmpty())
732 // Free the stream at the Producer, before the medium is deleted
733 GetImageProducer()->SetImage(OUString());
737 // the SfxMedium is not allowed to be created with an invalid URL, so we have to check this first
738 INetURLObject
aUrl(rURL
);
739 if (INetProtocol::NotValid
== aUrl
.GetProtocol() || aUrl
.IsExoticProtocol())
740 // we treat an invalid URL like we would treat no URL
743 if (!rURL
.isEmpty() && !::svt::GraphicAccess::isSupportedURL( rURL
) )
745 m_pMedium
.reset(new SfxMedium(rURL
, StreamMode::STD_READ
));
747 SfxObjectShell
*pObjSh
= GetObjectShell();
751 // Transfer target frame, so that javascript: URLs
752 // can also be "loaded"
753 const SfxMedium
*pShMedium
= pObjSh
->GetMedium();
755 m_pMedium
->SetLoadTargetFrame(pShMedium
->GetLoadTargetFrame());
758 m_bProdStarted
= false;
761 getPropertyValue(u
"Referer"_ustr
) >>= referer
;
762 if (!SvtSecurityOptions::isUntrustedReferer(referer
)) {
763 // Kick off download (caution: can be synchronous).
764 m_pMedium
->Download(LINK(this, OClickableImageBaseModel
, DownloadDoneLink
));
769 if ( ::svt::GraphicAccess::isSupportedURL( rURL
) )
770 GetImageProducer()->SetImage( rURL
);
771 GetImageProducer()->startProduction();
776 void OClickableImageBaseModel::DataAvailable()
781 GetImageProducer()->NewDataAvailable();
785 IMPL_LINK_NOARG( OClickableImageBaseModel
, DownloadDoneLink
, void*, void )
787 ::osl::MutexGuard
aGuard( m_aMutex
);
792 void OClickableImageBaseModel::_propertyChanged( const PropertyChangeEvent
& rEvt
)
794 // If a URL was set, it needs to be passed onto the ImageProducer.
795 ::osl::MutexGuard
aGuard(m_aMutex
);
796 SetURL( getString(rEvt
.NewValue
) );
800 Any
OClickableImageBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle
) const
804 case PROPERTY_ID_BUTTONTYPE
: return Any( FormButtonType_PUSH
);
805 case PROPERTY_ID_TARGET_URL
:
806 case PROPERTY_ID_TARGET_FRAME
: return Any( OUString() );
807 case PROPERTY_ID_DISPATCHURLINTERNAL
: return Any( false );
809 return OControlModel::getPropertyDefaultByHandle(nHandle
);
813 IMPL_LINK( OClickableImageBaseModel
, OnImageImportDone
, Graphic
*, i_pGraphic
, void )
815 const Reference
< XGraphic
> xGraphic( i_pGraphic
!= nullptr ? Graphic(i_pGraphic
->GetBitmapEx()).GetXGraphic() : nullptr );
816 if ( !xGraphic
.is() )
818 m_xGraphicObject
.clear();
822 m_xGraphicObject
= css::graphic::GraphicObject::create( m_xContext
);
823 m_xGraphicObject
->setGraphic( xGraphic
);
828 // OImageProducerThread_Impl
830 void OImageProducerThread_Impl::processEvent( ::cppu::OComponentHelper
*pCompImpl
,
831 const EventObject
* pEvt
,
832 const Reference
<XControl
>&,
835 static_cast<OClickableImageBaseControl
*>(pCompImpl
)->actionPerformed_Impl( true, *static_cast<const MouseEvent
*>(pEvt
) );
842 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */