LCOV - code coverage report
Current view: top level - forms/source/component - ImageControl.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 194 418 46.4 %
Date: 2014-11-03 Functions: 33 55 60.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include "ImageControl.hxx"
      21             : 
      22             : #include "property.hrc"
      23             : #include "frm_resource.hrc"
      24             : #include "frm_resource.hxx"
      25             : #include "services.hxx"
      26             : #include "componenttools.hxx"
      27             : 
      28             : #include <svtools/imageresourceaccess.hxx>
      29             : #include <unotools/ucblockbytes.hxx>
      30             : #include <sfx2/filedlghelper.hxx>
      31             : #include <com/sun/star/awt/PopupMenu.hpp>
      32             : #include <com/sun/star/awt/XPopupMenu.hpp>
      33             : #include <com/sun/star/awt/PopupMenuDirection.hpp>
      34             : #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
      35             : #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
      36             : #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
      37             : #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
      38             : #include <com/sun/star/sdbc/DataType.hpp>
      39             : #include <com/sun/star/awt/MouseButton.hpp>
      40             : #include <com/sun/star/awt/XWindow.hpp>
      41             : #include <com/sun/star/awt/XDialog.hpp>
      42             : #include <com/sun/star/io/XActiveDataSink.hpp>
      43             : #include <com/sun/star/io/NotConnectedException.hpp>
      44             : #include <com/sun/star/beans/PropertyValue.hpp>
      45             : #include <com/sun/star/graphic/XGraphic.hpp>
      46             : #include <com/sun/star/graphic/GraphicObject.hpp>
      47             : #include <tools/urlobj.hxx>
      48             : #include <tools/stream.hxx>
      49             : #include <tools/debug.hxx>
      50             : #include <tools/diagnose_ex.h>
      51             : #include <vcl/svapp.hxx>
      52             : #include <unotools/streamhelper.hxx>
      53             : #include <comphelper/guarding.hxx>
      54             : #include <comphelper/processfactory.hxx>
      55             : #include <unotools/ucbstreamhelper.hxx>
      56             : #include <svl/urihelper.hxx>
      57             : 
      58             : #include <boost/scoped_ptr.hpp>
      59             : 
      60             : #define ID_OPEN_GRAPHICS            1
      61             : #define ID_CLEAR_GRAPHICS           2
      62             : 
      63             : 
      64             : namespace frm
      65             : {
      66             : 
      67             : using namespace ::com::sun::star;
      68             : using namespace ::com::sun::star::uno;
      69             : using namespace ::com::sun::star::sdb;
      70             : using namespace ::com::sun::star::sdbc;
      71             : using namespace ::com::sun::star::sdbcx;
      72             : using namespace ::com::sun::star::beans;
      73             : using namespace ::com::sun::star::container;
      74             : using namespace ::com::sun::star::form;
      75             : using namespace ::com::sun::star::awt;
      76             : using namespace ::com::sun::star::io;
      77             : using namespace ::com::sun::star::ui::dialogs;
      78             : using namespace ::com::sun::star::lang;
      79             : using namespace ::com::sun::star::util;
      80             : using namespace ::com::sun::star::graphic;
      81             : using namespace ::com::sun::star::frame;
      82             : 
      83             : 
      84             : //= OImageControlModel
      85             : 
      86             : namespace
      87             : {
      88             :     enum ImageStoreType
      89             :     {
      90             :         ImageStoreBinary,
      91             :         ImageStoreLink,
      92             : 
      93             :         ImageStoreInvalid
      94             :     };
      95             : 
      96          24 :     ImageStoreType lcl_getImageStoreType( const sal_Int32 _nFieldType )
      97             :     {
      98             :         // binary/longvarchar types could be used to store images in binary representation
      99          24 :         if  (   ( _nFieldType == DataType::BINARY )
     100          24 :             ||  ( _nFieldType == DataType::VARBINARY )
     101          24 :             ||  ( _nFieldType == DataType::LONGVARBINARY )
     102          24 :             ||  ( _nFieldType == DataType::OTHER )
     103           0 :             ||  ( _nFieldType == DataType::OBJECT )
     104           0 :             ||  ( _nFieldType == DataType::BLOB )
     105           0 :             ||  ( _nFieldType == DataType::LONGVARCHAR )
     106           0 :             ||  ( _nFieldType == DataType::CLOB )
     107             :             )
     108          24 :             return ImageStoreBinary;
     109             : 
     110             :         // char types could be used to store links to images
     111           0 :         if  (   ( _nFieldType == DataType::CHAR )
     112           0 :             ||  ( _nFieldType == DataType::VARCHAR )
     113             :             )
     114           0 :             return ImageStoreLink;
     115             : 
     116           0 :         return ImageStoreInvalid;
     117             :     }
     118             : }
     119             : 
     120             : 
     121             : // OImageControlModel
     122             : 
     123             : 
     124             : 
     125          18 : InterfaceRef SAL_CALL OImageControlModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
     126             : {
     127          18 :     return *(new OImageControlModel( comphelper::getComponentContext(_rxFactory) ));
     128             : }
     129             : 
     130             : 
     131           0 : Sequence<Type> OImageControlModel::_getTypes()
     132             : {
     133             :     return concatSequences(
     134             :         OBoundControlModel::_getTypes(),
     135             :         OImageControlModel_Base::getTypes()
     136           0 :     );
     137             : }
     138             : 
     139             : 
     140          18 : OImageControlModel::OImageControlModel(const Reference<XComponentContext>& _rxFactory)
     141             :     :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_IMAGECONTROL, FRM_SUN_CONTROL_IMAGECONTROL, false, false, false )
     142             :                     // use the old control name for compytibility reasons
     143             :     ,m_pImageProducer( NULL )
     144             :     ,m_bExternalGraphic( true )
     145             :     ,m_bReadOnly( false )
     146             :     ,m_sImageURL()
     147          18 :     ,m_xGraphicObject()
     148             : {
     149          18 :     m_nClassId = FormComponentType::IMAGECONTROL;
     150          18 :     initOwnValueProperty( PROPERTY_IMAGE_URL );
     151             : 
     152          18 :     implConstruct();
     153          18 : }
     154             : 
     155             : 
     156           2 : OImageControlModel::OImageControlModel( const OImageControlModel* _pOriginal, const Reference< XComponentContext >& _rxFactory )
     157             :     :OBoundControlModel( _pOriginal, _rxFactory )
     158             :                 // use the old control name for compytibility reasons
     159             :     ,m_pImageProducer( NULL )
     160             :     ,m_bExternalGraphic( true )
     161             :     ,m_bReadOnly( _pOriginal->m_bReadOnly )
     162             :     ,m_sImageURL( _pOriginal->m_sImageURL )
     163           2 :     ,m_xGraphicObject( _pOriginal->m_xGraphicObject )
     164             : {
     165           2 :     implConstruct();
     166             : 
     167           2 :     osl_atomic_increment( &m_refCount );
     168             :     {
     169             :         // simulate a propertyChanged event for the ImageURL
     170           2 :         ::osl::MutexGuard aGuard( m_aMutex );
     171           2 :         impl_handleNewImageURL_lck( eOther );
     172             :     }
     173           2 :     osl_atomic_decrement( &m_refCount );
     174           2 : }
     175             : 
     176             : 
     177          20 : void OImageControlModel::implConstruct()
     178             : {
     179          20 :     m_pImageProducer = new ImageProducer;
     180          20 :     m_xImageProducer = m_pImageProducer;
     181          20 :     m_pImageProducer->SetDoneHdl( LINK( this, OImageControlModel, OnImageImportDone ) );
     182          20 : }
     183             : 
     184             : 
     185          60 : OImageControlModel::~OImageControlModel()
     186             : {
     187          20 :     if (!OComponentHelper::rBHelper.bDisposed)
     188             :     {
     189           0 :         acquire();
     190           0 :         dispose();
     191             :     }
     192             : 
     193          40 : }
     194             : 
     195             : // XCloneable
     196             : 
     197           2 : IMPLEMENT_DEFAULT_CLONING( OImageControlModel )
     198             : 
     199             : // XServiceInfo
     200             : 
     201          12 : StringSequence  OImageControlModel::getSupportedServiceNames() throw(std::exception)
     202             : {
     203          12 :     StringSequence aSupported = OBoundControlModel::getSupportedServiceNames();
     204          12 :     aSupported.realloc(aSupported.getLength() + 1);
     205             : 
     206          12 :     OUString*pArray = aSupported.getArray();
     207          12 :     pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_IMAGECONTROL;
     208          12 :     return aSupported;
     209             : }
     210             : 
     211             : 
     212        3376 : Any SAL_CALL OImageControlModel::queryAggregation(const Type& _rType) throw (RuntimeException, std::exception)
     213             : {
     214             :     // Order matters: we want to "override" the XImageProducer interface of the aggregate without
     215             :     // own XImageProducer interface, thus we need to query OImageControlModel_Base first
     216        3376 :     Any aReturn = OImageControlModel_Base::queryInterface( _rType );
     217             : 
     218             :     // BUT: _don't_ let it feel responsible for the XTypeProvider interface
     219             :     // (as this is implemented by our base class in the proper way)
     220        6752 :     if  (   _rType.equals( cppu::UnoType<XTypeProvider>::get() )
     221        3376 :         ||  !aReturn.hasValue()
     222             :         )
     223        1850 :         aReturn = OBoundControlModel::queryAggregation( _rType );
     224             : 
     225        3376 :     return aReturn;
     226             : }
     227             : 
     228             : 
     229           0 : bool OImageControlModel::approveDbColumnType( sal_Int32 _nColumnType )
     230             : {
     231           0 :     return ImageStoreInvalid != lcl_getImageStoreType( _nColumnType );
     232             : }
     233             : 
     234             : 
     235        2303 : void OImageControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
     236             : {
     237        2303 :     switch (nHandle)
     238             :     {
     239             :         case PROPERTY_ID_READONLY:
     240          88 :             rValue <<= m_bReadOnly;
     241          88 :             break;
     242             :         case PROPERTY_ID_IMAGE_URL:
     243          70 :             rValue <<= m_sImageURL;
     244          70 :             break;
     245             :         case PROPERTY_ID_GRAPHIC:
     246         124 :             rValue <<= m_xGraphicObject.is() ? m_xGraphicObject->getGraphic() : Reference< XGraphic >();
     247         124 :             break;
     248             :         default:
     249        2021 :             OBoundControlModel::getFastPropertyValue(rValue, nHandle);
     250             :     }
     251        2303 : }
     252             : 
     253             : 
     254         205 : void OImageControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( ::com::sun::star::uno::Exception, std::exception)
     255             : {
     256         205 :     switch (nHandle)
     257             :     {
     258             :         case PROPERTY_ID_READONLY :
     259             :             DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "OImageControlModel::setFastPropertyValue_NoBroadcast : invalid type !" );
     260          18 :             m_bReadOnly = getBOOL(rValue);
     261          18 :             break;
     262             : 
     263             :         case PROPERTY_ID_IMAGE_URL:
     264          10 :             OSL_VERIFY( rValue >>= m_sImageURL );
     265          10 :             impl_handleNewImageURL_lck( eOther );
     266             :             {
     267          10 :                 ControlModelLock aLock( *this );
     268             :                     // that's a fake ... onValuePropertyChange expects to receive the only lock to our instance,
     269             :                     // but we're already called with our mutex locked ...
     270          10 :                 onValuePropertyChange( aLock );
     271             :             }
     272          10 :             break;
     273             : 
     274             :         case PROPERTY_ID_GRAPHIC:
     275             :         {
     276           2 :             Reference< XGraphic > xGraphic;
     277           2 :             OSL_VERIFY( rValue >>= xGraphic );
     278           2 :             if ( !xGraphic.is() )
     279           0 :                 m_xGraphicObject.clear();
     280             :             else
     281             :             {
     282           2 :                 m_xGraphicObject = GraphicObject::create( m_xContext );
     283           2 :                 m_xGraphicObject->setGraphic( xGraphic );
     284             :             }
     285             : 
     286           2 :             if ( m_bExternalGraphic )
     287             :             {
     288             :                 // if that's an external graphic, i.e. one which has not been loaded by ourselves in response to a
     289             :                 // new image URL, then also adjust our ImageURL.
     290           0 :                 OUString sNewImageURL;
     291           0 :                 if ( m_xGraphicObject.is() )
     292             :                 {
     293           0 :                     sNewImageURL = "vnd.sun.star.GraphicObject:";
     294           0 :                     sNewImageURL = sNewImageURL + m_xGraphicObject->getUniqueID();
     295             :                 }
     296           0 :                 m_sImageURL = sNewImageURL;
     297             :                 // TODO: speaking strictly, this would need to be notified, since ImageURL is a bound property. However,
     298             :                 // this method here is called with a locked mutex, so we cannot simply call listeners ...
     299             :                 // I think the missing notification (and thus clients which potentially cannot observe the change)
     300             :                 // is less severe than the potential deadlock ...
     301           2 :             }
     302             :         }
     303           2 :         break;
     304             : 
     305             :         default:
     306         175 :             OBoundControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue);
     307         175 :             break;
     308             :     }
     309         205 : }
     310             : 
     311             : 
     312         661 : sal_Bool OImageControlModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue)
     313             :                                 throw( IllegalArgumentException )
     314             : {
     315         661 :     switch (nHandle)
     316             :     {
     317             :         case PROPERTY_ID_READONLY :
     318          58 :             return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bReadOnly);
     319             : 
     320             :         case PROPERTY_ID_IMAGE_URL:
     321          50 :             return tryPropertyValue( rConvertedValue, rOldValue, rValue, m_sImageURL );
     322             : 
     323             :         case PROPERTY_ID_GRAPHIC:
     324             :         {
     325          56 :             const Reference< XGraphic > xGraphic( getFastPropertyValue( PROPERTY_ID_GRAPHIC ), UNO_QUERY );
     326          56 :             return tryPropertyValue( rConvertedValue, rOldValue, rValue, xGraphic );
     327             :         }
     328             : 
     329             :         default:
     330         497 :             return OBoundControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue);
     331             :     }
     332             : }
     333             : 
     334             : 
     335          22 : void OImageControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
     336             : {
     337          22 :     BEGIN_DESCRIBE_PROPERTIES( 4, OBoundControlModel )
     338          22 :         DECL_IFACE_PROP2( GRAPHIC,   XGraphic,        BOUND, TRANSIENT );
     339          22 :         DECL_PROP1      ( IMAGE_URL, OUString, BOUND );
     340          22 :         DECL_BOOL_PROP1 ( READONLY,                   BOUND );
     341          22 :         DECL_PROP1      ( TABINDEX,  sal_Int16,       BOUND );
     342             :     END_DESCRIBE_PROPERTIES();
     343          22 : }
     344             : 
     345             : 
     346          22 : void OImageControlModel::describeAggregateProperties( Sequence< Property >& /* [out] */ o_rAggregateProperties ) const
     347             : {
     348          22 :     OBoundControlModel::describeAggregateProperties( o_rAggregateProperties );
     349             :     // remove ImageURL and Graphic properties, we "overload" them. This is because our aggregate synchronizes those
     350             :     // two, but we have an own sychronization mechanism.
     351          22 :     RemoveProperty( o_rAggregateProperties, PROPERTY_IMAGE_URL );
     352          22 :     RemoveProperty( o_rAggregateProperties, PROPERTY_GRAPHIC );
     353          22 : }
     354             : 
     355             : 
     356           2 : OUString OImageControlModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     357             : {
     358           2 :     return OUString(FRM_COMPONENT_IMAGECONTROL);  // old (non-sun) name for compatibility !
     359             : }
     360             : 
     361             : 
     362           2 : void OImageControlModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException, std::exception)
     363             : {
     364             :     // Base class
     365           2 :     OBoundControlModel::write(_rxOutStream);
     366             :     // Version
     367           2 :     _rxOutStream->writeShort(0x0003);
     368             :     // Name
     369           2 :     _rxOutStream->writeBoolean(m_bReadOnly);
     370           2 :     writeHelpTextCompatibly(_rxOutStream);
     371             :     // from version 0x0003 : common properties
     372           2 :     writeCommonProperties(_rxOutStream);
     373           2 : }
     374             : 
     375             : 
     376           2 : void OImageControlModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException, std::exception)
     377             : {
     378           2 :     OBoundControlModel::read(_rxInStream);
     379             : 
     380             :     // Version
     381           2 :     sal_uInt16 nVersion = _rxInStream->readShort();
     382           2 :     switch (nVersion)
     383             :     {
     384             :         case 0x0001:
     385           0 :             m_bReadOnly = _rxInStream->readBoolean();
     386           0 :             break;
     387             :         case 0x0002:
     388           0 :             m_bReadOnly = _rxInStream->readBoolean();
     389           0 :             readHelpTextCompatibly(_rxInStream);
     390           0 :             break;
     391             :         case 0x0003:
     392           2 :             m_bReadOnly = _rxInStream->readBoolean();
     393           2 :             readHelpTextCompatibly(_rxInStream);
     394           2 :             readCommonProperties(_rxInStream);
     395           2 :             break;
     396             :         default :
     397             :             OSL_FAIL("OImageControlModel::read : unknown version !");
     398           0 :             m_bReadOnly = false;
     399           0 :             defaultCommonProperties();
     400           0 :             break;
     401             :     }
     402             :     // Display default values after read
     403           2 :     if ( !getControlSource().isEmpty() )
     404             :     {   // (not if we don't have a control source - the "State" property acts like it is persistent, then
     405           2 :         ::osl::MutexGuard aGuard(m_aMutex); // resetNoBroadcast expects this mutex guarding
     406           2 :         resetNoBroadcast();
     407             :     }
     408           2 : }
     409             : 
     410             : 
     411          12 : bool OImageControlModel::impl_updateStreamForURL_lck( const OUString& _rURL, ValueChangeInstigator _eInstigator )
     412             : {
     413             :     // create a stream for the image specified by the URL
     414          12 :     boost::scoped_ptr< SvStream > pImageStream;
     415          24 :     Reference< XInputStream > xImageStream;
     416             : 
     417          12 :     if ( ::svt::GraphicAccess::isSupportedURL( _rURL ) )
     418             :     {
     419           0 :         xImageStream = ::svt::GraphicAccess::getImageXStream( getContext(), _rURL );
     420             :     }
     421             :     else
     422             :     {
     423          12 :         pImageStream.reset( ::utl::UcbStreamHelper::CreateStream( _rURL, STREAM_READ ) );
     424          12 :         bool bSetNull = ( pImageStream.get() == NULL ) || ( ERRCODE_NONE != pImageStream->GetErrorCode() );
     425             : 
     426          12 :         if ( !bSetNull )
     427             :         {
     428             :             // get the size of the stream
     429           2 :             sal_uInt64 const nSize = pImageStream->remainingSize();
     430           2 :             if (pImageStream->GetBufferSize() < 8192)
     431           2 :                 pImageStream->SetBufferSize(8192);
     432           2 :             pImageStream->Seek(STREAM_SEEK_TO_BEGIN);
     433             : 
     434           2 :             xImageStream = new ::utl::OInputStreamHelper( new SvLockBytes( pImageStream.get(), false ), nSize );
     435             :         }
     436             :     }
     437             : 
     438          12 :     if ( xImageStream.is() )
     439             :     {
     440           2 :         if ( m_xColumnUpdate.is() )
     441           0 :             m_xColumnUpdate->updateBinaryStream( xImageStream, xImageStream->available() );
     442             :         else
     443           2 :             setControlValue( makeAny( xImageStream ), _eInstigator );
     444           2 :         xImageStream->closeInput();
     445           2 :         return true;
     446             :     }
     447             : 
     448          22 :     return false;
     449             : }
     450             : 
     451             : 
     452          12 : bool OImageControlModel::impl_handleNewImageURL_lck( ValueChangeInstigator _eInstigator )
     453             : {
     454          12 :     switch ( lcl_getImageStoreType( getFieldType() ) )
     455             :     {
     456             :     case ImageStoreBinary:
     457          12 :         if ( impl_updateStreamForURL_lck( m_sImageURL, _eInstigator ) )
     458           2 :             return true;
     459          10 :         break;
     460             : 
     461             :     case ImageStoreLink:
     462             :     {
     463           0 :         OUString sCommitURL( m_sImageURL );
     464           0 :         if ( !m_sDocumentURL.isEmpty() )
     465           0 :             sCommitURL = URIHelper::simpleNormalizedMakeRelative( m_sDocumentURL, sCommitURL );
     466             :         OSL_ENSURE( m_xColumnUpdate.is(), "OImageControlModel::impl_handleNewImageURL_lck: no bound field, but ImageStoreLink?!" );
     467           0 :         if ( m_xColumnUpdate.is() )
     468             :         {
     469           0 :             m_xColumnUpdate->updateString( sCommitURL );
     470           0 :             return true;
     471           0 :         }
     472             :     }
     473           0 :     break;
     474             : 
     475             :     case ImageStoreInvalid:
     476             :         OSL_FAIL( "OImageControlModel::impl_handleNewImageURL_lck: image storage type type!" );
     477           0 :         break;
     478             :     }
     479             : 
     480             :     // if we're here, then the above code was unable to update our field/control from the given URL
     481             :     // => fall back to NULL/VOID
     482          10 :     if ( m_xColumnUpdate.is() )
     483           0 :         m_xColumnUpdate->updateNull();
     484             :     else
     485          10 :         setControlValue( Any(), _eInstigator );
     486             : 
     487          10 :     return true;
     488             : }
     489             : 
     490             : 
     491           0 : bool OImageControlModel::commitControlValueToDbColumn( bool _bPostReset )
     492             : {
     493           0 :     if ( _bPostReset )
     494             :     {
     495             :         // since this is a "commit after reset", we can simply update the column
     496             :         // with null - this is our "default" which we were just reset to
     497           0 :         if ( m_xColumnUpdate.is() )
     498           0 :             m_xColumnUpdate->updateNull();
     499             :     }
     500             :     else
     501             :     {
     502           0 :         ::osl::MutexGuard aGuard(m_aMutex);
     503           0 :         return impl_handleNewImageURL_lck( eDbColumnBinding );
     504             :     }
     505             : 
     506           0 :     return true;
     507             : }
     508             : 
     509             : 
     510             : namespace
     511             : {
     512           0 :     bool lcl_isValidDocumentURL( const OUString& _rDocURL )
     513             :     {
     514           0 :         return ( !_rDocURL.isEmpty() && _rDocURL != "private:object" );
     515             :     }
     516             : }
     517             : 
     518             : 
     519           0 : void OImageControlModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm )
     520             : {
     521           0 :     OBoundControlModel::onConnectedDbColumn( _rxForm );
     522             : 
     523             :     try
     524             :     {
     525           0 :         Reference< XModel > xDocument( getXModel( *this ) );
     526           0 :         if ( xDocument.is() )
     527             :         {
     528           0 :             m_sDocumentURL = xDocument->getURL();
     529           0 :             if ( !lcl_isValidDocumentURL( m_sDocumentURL ) )
     530             :             {
     531           0 :                 Reference< XChild > xAsChild( xDocument, UNO_QUERY );
     532           0 :                 while ( xAsChild.is() && !lcl_isValidDocumentURL( m_sDocumentURL ) )
     533             :                 {
     534           0 :                     xDocument.set( xAsChild->getParent(), UNO_QUERY );
     535           0 :                     if ( xDocument.is() )
     536           0 :                         m_sDocumentURL = xDocument->getURL();
     537           0 :                     xAsChild.set( xDocument, UNO_QUERY );
     538           0 :                 }
     539             :             }
     540           0 :         }
     541             :     }
     542           0 :     catch( const Exception& )
     543             :     {
     544             :         DBG_UNHANDLED_EXCEPTION();
     545             :     }
     546           0 : }
     547             : 
     548             : 
     549           0 : void OImageControlModel::onDisconnectedDbColumn()
     550             : {
     551           0 :     OBoundControlModel::onDisconnectedDbColumn();
     552             : 
     553           0 :     m_sDocumentURL = OUString();
     554           0 : }
     555             : 
     556             : 
     557           0 : Any OImageControlModel::translateDbColumnToControlValue()
     558             : {
     559           0 :     switch ( lcl_getImageStoreType( getFieldType() ) )
     560             :     {
     561             :     case ImageStoreBinary:
     562             :     {
     563           0 :         Reference< XInputStream > xImageStream( m_xColumn->getBinaryStream() );
     564           0 :         if ( m_xColumn->wasNull() )
     565           0 :             xImageStream.clear();
     566           0 :         return makeAny( xImageStream );
     567             :     }
     568             :     case ImageStoreLink:
     569             :     {
     570           0 :         OUString sImageLink( m_xColumn->getString() );
     571           0 :         if ( !m_sDocumentURL.isEmpty() )
     572           0 :             sImageLink = INetURLObject::GetAbsURL( m_sDocumentURL, sImageLink );
     573           0 :         return makeAny( sImageLink );
     574             :     }
     575             :     case ImageStoreInvalid:
     576             :         OSL_FAIL( "OImageControlModel::translateDbColumnToControlValue: invalid field type!" );
     577           0 :         break;
     578             :     }
     579           0 :     return Any();
     580             : }
     581             : 
     582             : 
     583           0 : Any OImageControlModel::getControlValue( ) const
     584             : {
     585           0 :     return makeAny( m_sImageURL );
     586             : }
     587             : 
     588             : 
     589          12 : void OImageControlModel::doSetControlValue( const Any& _rValue )
     590             : {
     591             :     DBG_ASSERT( GetImageProducer() && m_xImageProducer.is(), "OImageControlModel::doSetControlValue: no image producer!" );
     592          12 :     if ( !GetImageProducer() || !m_xImageProducer.is() )
     593          12 :         return;
     594             : 
     595          12 :     bool bStartProduction = false;
     596          12 :     switch ( lcl_getImageStoreType( getFieldType() ) )
     597             :     {
     598             :     case ImageStoreBinary:
     599             :     {
     600             :         // give the image producer the stream
     601          12 :         Reference< XInputStream > xInStream;
     602          12 :         _rValue >>= xInStream;
     603          12 :         GetImageProducer()->setImage( xInStream );
     604          12 :         bStartProduction = true;
     605             :     }
     606          12 :     break;
     607             : 
     608             :     case ImageStoreLink:
     609             :     {
     610           0 :         OUString sImageURL;
     611           0 :         _rValue >>= sImageURL;
     612           0 :         GetImageProducer()->SetImage( sImageURL );
     613           0 :         bStartProduction = true;
     614             :     }
     615           0 :     break;
     616             : 
     617             :     case ImageStoreInvalid:
     618             :         OSL_FAIL( "OImageControlModel::doSetControlValue: invalid field type!" );
     619           0 :         break;
     620             : 
     621             :     }   // switch ( lcl_getImageStoreType( getFieldType() ) )
     622             : 
     623          12 :     if ( bStartProduction )
     624             :     {
     625             :         // start production
     626          12 :         Reference< XImageProducer > xProducer = m_xImageProducer;
     627             :         {
     628             :             // release our mutex once (it's acquired in the calling method!), as starting the image production may
     629             :             // result in the locking of the solar mutex (unfortunately the default implementation of our aggregate,
     630             :             // VCLXImageControl, does this locking)
     631          12 :             MutexRelease aRelease(m_aMutex);
     632          12 :             xProducer->startProduction();
     633          12 :         }
     634             :     }
     635             : }
     636             : 
     637             : // OComponentHelper
     638             : 
     639          20 : void SAL_CALL OImageControlModel::disposing()
     640             : {
     641          20 :     OBoundControlModel::disposing();
     642          20 : }
     643             : 
     644             : 
     645           6 : void OImageControlModel::resetNoBroadcast()
     646             : {
     647           6 :     if ( hasField() )          // only reset when we are connected to a column
     648           0 :         OBoundControlModel::resetNoBroadcast( );
     649           6 : }
     650             : 
     651             : 
     652           2 : Reference< XImageProducer > SAL_CALL OImageControlModel::getImageProducer() throw ( RuntimeException, std::exception)
     653             : {
     654           2 :     return this;
     655             : }
     656             : 
     657             : 
     658           0 : void SAL_CALL OImageControlModel::addConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException, std::exception)
     659             : {
     660           0 :     GetImageProducer()->addConsumer( _rxConsumer );
     661           0 : }
     662             : 
     663             : 
     664           0 : void SAL_CALL OImageControlModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException, std::exception)
     665             : {
     666           0 :     GetImageProducer()->removeConsumer( _rxConsumer );
     667           0 : }
     668             : 
     669             : 
     670           0 : void SAL_CALL OImageControlModel::startProduction(  ) throw (RuntimeException, std::exception)
     671             : {
     672           0 :     GetImageProducer()->startProduction();
     673           0 : }
     674             : 
     675             : 
     676          24 : IMPL_LINK( OImageControlModel, OnImageImportDone, ::Graphic*, i_pGraphic )
     677             : {
     678          12 :     const Reference< XGraphic > xGraphic( i_pGraphic != NULL ? Image( i_pGraphic->GetBitmapEx() ).GetXGraphic() : NULL );
     679          12 :     m_bExternalGraphic = false;
     680             :     try
     681             :     {
     682          12 :         setPropertyValue( PROPERTY_GRAPHIC, makeAny( xGraphic ) );
     683             :     }
     684           0 :     catch ( const Exception& )
     685             :     {
     686             :         DBG_UNHANDLED_EXCEPTION();
     687             :     }
     688          12 :     m_bExternalGraphic = true;
     689          12 :     return 1L;
     690             : }
     691             : 
     692             : 
     693             : // OImageControlControl
     694             : 
     695             : 
     696             : 
     697           2 : InterfaceRef SAL_CALL OImageControlControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
     698             : {
     699           2 :     return *(new OImageControlControl( comphelper::getComponentContext(_rxFactory) ));
     700             : }
     701             : 
     702             : 
     703           0 : Sequence<Type> OImageControlControl::_getTypes()
     704             : {
     705             :     return concatSequences(
     706             :         OBoundControl::_getTypes(),
     707             :         OImageControlControl_Base::getTypes()
     708           0 :     );
     709             : }
     710             : 
     711             : 
     712           2 : OImageControlControl::OImageControlControl(const Reference<XComponentContext>& _rxFactory)
     713             :     :OBoundControl(_rxFactory, VCL_CONTROL_IMAGECONTROL)
     714           2 :     ,m_aModifyListeners( m_aMutex )
     715             : {
     716           2 :     increment(m_refCount);
     717             :     {
     718             :         // Add as Focus- and MouseListener
     719           2 :         Reference< XWindow > xComp;
     720           2 :         query_aggregation( m_xAggregate, xComp );
     721           2 :         if ( xComp.is() )
     722           2 :             xComp->addMouseListener( this );
     723             :     }
     724           2 :     decrement(m_refCount);
     725           2 : }
     726             : 
     727             : 
     728          70 : Any SAL_CALL OImageControlControl::queryAggregation(const Type& _rType) throw (RuntimeException, std::exception)
     729             : {
     730          70 :     Any aReturn = OBoundControl::queryAggregation( _rType );
     731          70 :     if ( !aReturn.hasValue() )
     732           8 :         aReturn = ::cppu::queryInterface(
     733             :             _rType,
     734             :             static_cast< XMouseListener* >( this ),
     735             :             static_cast< XModifyBroadcaster* >( this )
     736           4 :         );
     737             : 
     738          70 :     return aReturn;
     739             : }
     740             : 
     741             : 
     742           0 : StringSequence  OImageControlControl::getSupportedServiceNames() throw(std::exception)
     743             : {
     744           0 :     StringSequence aSupported = OBoundControl::getSupportedServiceNames();
     745           0 :     aSupported.realloc(aSupported.getLength() + 1);
     746             : 
     747           0 :     OUString*pArray = aSupported.getArray();
     748           0 :     pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_IMAGECONTROL;
     749           0 :     return aSupported;
     750             : }
     751             : 
     752             : 
     753           0 : void SAL_CALL OImageControlControl::addModifyListener( const Reference< XModifyListener >& _Listener ) throw (RuntimeException, std::exception)
     754             : {
     755           0 :     m_aModifyListeners.addInterface( _Listener );
     756           0 : }
     757             : 
     758             : 
     759           0 : void SAL_CALL OImageControlControl::removeModifyListener( const Reference< XModifyListener >& _Listener ) throw (RuntimeException, std::exception)
     760             : {
     761           0 :     m_aModifyListeners.removeInterface( _Listener );
     762           0 : }
     763             : 
     764             : 
     765           2 : void SAL_CALL OImageControlControl::disposing()
     766             : {
     767           2 :     EventObject aEvent( *this );
     768           2 :     m_aModifyListeners.disposeAndClear( aEvent );
     769             : 
     770           2 :     OBoundControl::disposing();
     771           2 : }
     772             : 
     773             : 
     774           2 : void SAL_CALL OImageControlControl::disposing( const EventObject& _Event ) throw(RuntimeException, std::exception)
     775             : {
     776           2 :     OBoundControl::disposing( _Event );
     777           2 : }
     778             : 
     779             : 
     780           0 : void OImageControlControl::implClearGraphics( bool _bForce )
     781             : {
     782           0 :     Reference< XPropertySet > xSet( getModel(), UNO_QUERY );
     783           0 :     if ( xSet.is() )
     784             :     {
     785           0 :         if ( _bForce )
     786             :         {
     787           0 :             OUString sOldImageURL;
     788           0 :             xSet->getPropertyValue( PROPERTY_IMAGE_URL ) >>= sOldImageURL;
     789             : 
     790           0 :             if ( sOldImageURL.isEmpty() )
     791             :                 // the ImageURL is already empty, so simply setting a new empty one would not suffice
     792             :                 // (since it would be ignored)
     793           0 :                 xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( OUString( "private:emptyImage" ) ) );
     794             :                     // (the concrete URL we're passing here doens't matter. It's important that
     795             :                     // the model cannot resolve it to a a valid resource describing an image stream
     796             :         }
     797             : 
     798           0 :         xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( OUString() ) );
     799           0 :     }
     800           0 : }
     801             : 
     802             : 
     803           0 : bool OImageControlControl::implInsertGraphics()
     804             : {
     805           0 :     Reference< XPropertySet > xSet( getModel(), UNO_QUERY );
     806           0 :     if ( !xSet.is() )
     807           0 :         return false;
     808             : 
     809           0 :     OUString sTitle = FRM_RES_STRING(RID_STR_IMPORT_GRAPHIC);
     810             :     // build some arguments for the upcoming dialog
     811             :     try
     812             :     {
     813           0 :         ::sfx2::FileDialogHelper aDialog( TemplateDescription::FILEOPEN_LINK_PREVIEW, SFXWB_GRAPHIC );
     814           0 :         aDialog.SetTitle( sTitle );
     815             : 
     816           0 :         Reference< XFilePickerControlAccess > xController( aDialog.GetFilePicker(), UNO_QUERY_THROW );
     817           0 :         xController->setValue(ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0, css::uno::Any(true));
     818             : 
     819           0 :         Reference<XPropertySet> xBoundField;
     820           0 :         if ( hasProperty( PROPERTY_BOUNDFIELD, xSet ) )
     821           0 :             xSet->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= xBoundField;
     822           0 :         bool bHasField = xBoundField.is();
     823             : 
     824             :         // if the control is bound to a DB field, then it's not possible to decide whether or not to link
     825           0 :         xController->enableControl(ExtendedFilePickerElementIds::CHECKBOX_LINK, !bHasField );
     826             : 
     827             :         // if the control is bound to a DB field, then linking of the image depends on the type of the field
     828           0 :         bool bImageIsLinked = true;
     829           0 :         if ( bHasField )
     830             :         {
     831           0 :             sal_Int32 nFieldType = DataType::OTHER;
     832           0 :             OSL_VERIFY( xBoundField->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType );
     833           0 :             bImageIsLinked = ( lcl_getImageStoreType( nFieldType ) == ImageStoreLink );
     834             :         }
     835           0 :         xController->setValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, makeAny( bImageIsLinked ) );
     836             : 
     837           0 :         if ( ERRCODE_NONE == aDialog.Execute() )
     838             :         {
     839             :             // reset the url property in case it already has the value we're about to set - in this case
     840             :             // our propertyChanged would not get called without this.
     841           0 :             implClearGraphics( false );
     842           0 :             bool bIsLink = false;
     843           0 :             xController->getValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0) >>= bIsLink;
     844             :             // Force bIsLink to be sal_True if we're bound to a field. Though we initialized the file picker with IsLink=TRUE
     845             :             // in this case, and disabled the respective control, there might be picker implementations which do not
     846             :             // respect this, and return IsLink=FALSE here. In this case, "normalize" the flag.
     847             :             // #i112659#
     848           0 :             bIsLink |= bHasField;
     849           0 :             if ( !bIsLink )
     850             :             {
     851           0 :                 Graphic aGraphic;
     852           0 :                 aDialog.GetGraphic( aGraphic );
     853           0 :                  xSet->setPropertyValue( PROPERTY_GRAPHIC, makeAny( aGraphic.GetXGraphic() ) );
     854             :             }
     855             :             else
     856           0 :                 xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( OUString( aDialog.GetPath() ) ) );
     857             : 
     858           0 :             return true;
     859           0 :         }
     860             :     }
     861           0 :     catch(const Exception&)
     862             :     {
     863             :         OSL_FAIL("OImageControlControl::implInsertGraphics: caught an exception while attempting to execute the FilePicker!");
     864             :     }
     865           0 :     return false;
     866             : }
     867             : 
     868             : 
     869           0 : bool OImageControlControl::impl_isEmptyGraphics_nothrow() const
     870             : {
     871           0 :     bool bIsEmpty = true;
     872             : 
     873             :     try
     874             :     {
     875           0 :         Reference< XPropertySet > xModelProps( const_cast< OImageControlControl* >( this )->getModel(), UNO_QUERY_THROW );
     876           0 :         Reference< XGraphic > xGraphic;
     877           0 :         OSL_VERIFY( xModelProps->getPropertyValue("Graphic") >>= xGraphic );
     878           0 :         bIsEmpty = !xGraphic.is();
     879             :     }
     880           0 :     catch( const Exception& )
     881             :     {
     882             :         DBG_UNHANDLED_EXCEPTION();
     883             :     }
     884             : 
     885           0 :     return bIsEmpty;
     886             : }
     887             : 
     888             : // MouseListener
     889             : 
     890           0 : void OImageControlControl::mousePressed(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     891             : {
     892           0 :     SolarMutexGuard aGuard;
     893             : 
     894           0 :     if (e.Buttons != MouseButton::LEFT)
     895           0 :         return;
     896             : 
     897           0 :     bool bModified = false;
     898             :     // is this a request for a context menu?
     899           0 :     if ( e.PopupTrigger )
     900             :     {
     901           0 :         Reference< XPopupMenu > xMenu( awt::PopupMenu::create( m_xContext ) );
     902             :         DBG_ASSERT( xMenu.is(), "OImageControlControl::mousePressed: could not create a popup menu!" );
     903             : 
     904           0 :         Reference< XWindowPeer > xWindowPeer = getPeer();
     905             :         DBG_ASSERT( xWindowPeer.is(), "OImageControlControl::mousePressed: no window!" );
     906             : 
     907           0 :         if ( xMenu.is() && xWindowPeer.is() )
     908             :         {
     909           0 :             xMenu->insertItem( ID_OPEN_GRAPHICS, FRM_RES_STRING( RID_STR_OPEN_GRAPHICS ), 0, 0 );
     910           0 :             xMenu->insertItem( ID_CLEAR_GRAPHICS, FRM_RES_STRING( RID_STR_CLEAR_GRAPHICS ), 0, 1 );
     911             : 
     912             :             // check if the ImageURL is empty
     913           0 :             if ( impl_isEmptyGraphics_nothrow() )
     914           0 :                 xMenu->enableItem( ID_CLEAR_GRAPHICS, sal_False );
     915             : 
     916           0 :             awt::Rectangle aRect( e.X, e.Y, 0, 0 );
     917           0 :             if ( ( e.X < 0 ) || ( e.Y < 0 ) )
     918             :             {   // context menu triggered by keyboard
     919             :                 // position it in the center of the control
     920           0 :                 Reference< XWindow > xWindow( static_cast< ::cppu::OWeakObject* >( this ), UNO_QUERY );
     921             :                 OSL_ENSURE( xWindow.is(), "OImageControlControl::mousePressed: me not a window? How this?" );
     922           0 :                 if ( xWindow.is() )
     923             :                 {
     924           0 :                     awt::Rectangle aPosSize = xWindow->getPosSize();
     925           0 :                     aRect.X = aPosSize.Width / 2;
     926           0 :                     aRect.Y = aPosSize.Height / 2;
     927           0 :                 }
     928             :             }
     929             : 
     930           0 :             const sal_Int16 nResult = xMenu->execute( xWindowPeer, aRect, PopupMenuDirection::EXECUTE_DEFAULT );
     931             : 
     932           0 :             switch ( nResult )
     933             :             {
     934             :             case ID_OPEN_GRAPHICS:
     935           0 :                 implInsertGraphics();
     936           0 :                 bModified = true;
     937           0 :                 break;
     938             : 
     939             :             case ID_CLEAR_GRAPHICS:
     940           0 :                 implClearGraphics( true );
     941           0 :                 bModified = true;
     942           0 :                 break;
     943             :             }
     944           0 :         }
     945             :     }
     946             :     else
     947             :     {
     948             : 
     949             :         // Double click
     950           0 :         if (e.ClickCount == 2)
     951             :         {
     952             : 
     953           0 :             Reference<XPropertySet>  xSet(getModel(), UNO_QUERY);
     954           0 :             if (!xSet.is())
     955           0 :                 return;
     956             : 
     957             :             // If the Control is not bound, do not display a dialog (because the to-be-sent URL would be invalid anyway)
     958           0 :             Reference<XPropertySet> xBoundField;
     959           0 :             if (hasProperty(PROPERTY_BOUNDFIELD, xSet))
     960             :                 xBoundField.set(
     961           0 :                     xSet->getPropertyValue(PROPERTY_BOUNDFIELD),
     962           0 :                     css::uno::UNO_QUERY);
     963           0 :             if (!xBoundField.is())
     964             :             {
     965             :                 // but only if our IMAGE_URL property is handled as if it is transient, which is equivalent to
     966             :                 // an empty control source
     967           0 :                 if ( !hasProperty(PROPERTY_CONTROLSOURCE, xSet) || !::comphelper::getString(xSet->getPropertyValue(PROPERTY_CONTROLSOURCE)).isEmpty() )
     968           0 :                     return;
     969             :             }
     970             : 
     971           0 :             bool bReadOnly = false;
     972           0 :             xSet->getPropertyValue(PROPERTY_READONLY) >>= bReadOnly;
     973           0 :             if (bReadOnly)
     974           0 :                 return;
     975             : 
     976           0 :             if ( implInsertGraphics() )
     977           0 :                 bModified = true;
     978             :         }
     979             :     }
     980             : 
     981           0 :     if ( bModified )
     982             :     {
     983           0 :         EventObject aEvent( *this );
     984           0 :         m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent );
     985           0 :     }
     986             : }
     987             : 
     988             : 
     989           0 : void SAL_CALL OImageControlControl::mouseReleased(const awt::MouseEvent& /*e*/) throw ( RuntimeException, std::exception )
     990             : {
     991           0 : }
     992             : 
     993             : 
     994           0 : void SAL_CALL OImageControlControl::mouseEntered(const awt::MouseEvent& /*e*/) throw ( RuntimeException, std::exception )
     995             : {
     996           0 : }
     997             : 
     998             : 
     999           0 : void SAL_CALL OImageControlControl::mouseExited(const awt::MouseEvent& /*e*/) throw ( RuntimeException, std::exception )
    1000             : {
    1001           0 : }
    1002             : 
    1003             : 
    1004         192 : }   // namespace frm
    1005             : 
    1006             : 
    1007             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10