LCOV - code coverage report
Current view: top level - svtools/source/misc - embedhlp.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 288 457 63.0 %
Date: 2014-11-03 Functions: 46 51 90.2 %
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             : 
      21             : #include <svtools/embedhlp.hxx>
      22             : #include <vcl/graphicfilter.hxx>
      23             : #include <svtools/svtools.hrc>
      24             : #include <svtools/svtresid.hxx>
      25             : 
      26             : #include <comphelper/embeddedobjectcontainer.hxx>
      27             : #include <comphelper/seqstream.hxx>
      28             : #include <toolkit/helper/vclunohelper.hxx>
      29             : #include <unotools/ucbstreamhelper.hxx>
      30             : #include <unotools/streamwrap.hxx>
      31             : #include <com/sun/star/chart2/XChartDocument.hpp>
      32             : #include <com/sun/star/chart2/XCoordinateSystem.hpp>
      33             : #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
      34             : #include <com/sun/star/chart2/XDiagram.hpp>
      35             : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
      36             : #include <com/sun/star/chart2/XChartType.hpp>
      37             : #include <tools/globname.hxx>
      38             : #include <comphelper/classids.hxx>
      39             : #include <com/sun/star/util/XModifyListener.hpp>
      40             : #include <com/sun/star/util/XModifiable.hpp>
      41             : #include <com/sun/star/embed/Aspects.hpp>
      42             : #include <com/sun/star/embed/EmbedMisc.hpp>
      43             : #include <com/sun/star/embed/EmbedStates.hpp>
      44             : #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
      45             : #include <com/sun/star/embed/XEmbeddedObject.hpp>
      46             : #include <com/sun/star/embed/XStateChangeListener.hpp>
      47             : #include <com/sun/star/datatransfer/XTransferable.hpp>
      48             : #include <com/sun/star/chart2/XDefaultSizeTransmitter.hpp>
      49             : #include <cppuhelper/implbase4.hxx>
      50             : #include <vcl/svapp.hxx>
      51             : #include <osl/mutex.hxx>
      52             : #include <boost/scoped_ptr.hpp>
      53             : 
      54             : using namespace com::sun::star;
      55             : 
      56             : namespace svt {
      57             : 
      58        4648 : class EmbedEventListener_Impl : public ::cppu::WeakImplHelper4 < embed::XStateChangeListener,
      59             :                                                                  document::XEventListener,
      60             :                                                                  util::XModifyListener,
      61             :                                                                  util::XCloseListener >
      62             : {
      63             : public:
      64             :     EmbeddedObjectRef*          pObject;
      65             :     sal_Int32                   nState;
      66             : 
      67        2354 :                                 EmbedEventListener_Impl( EmbeddedObjectRef* p ) :
      68             :                                     pObject(p)
      69        2354 :                                     , nState(-1)
      70        2354 :                                 {}
      71             : 
      72             :     static EmbedEventListener_Impl* Create( EmbeddedObjectRef* );
      73             : 
      74             :     virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
      75             :                                     throw (embed::WrongStateException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
      76             :     virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
      77             :                                     throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
      78             :     virtual void SAL_CALL queryClosing( const lang::EventObject& Source, sal_Bool GetsOwnership )
      79             :                                     throw (util::CloseVetoException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
      80             :     virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
      81             :     virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
      82             :     virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
      83             :     virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      84             : };
      85             : 
      86        2354 : EmbedEventListener_Impl* EmbedEventListener_Impl::Create( EmbeddedObjectRef* p )
      87             : {
      88        2354 :     EmbedEventListener_Impl* xRet = new EmbedEventListener_Impl( p );
      89        2354 :     xRet->acquire();
      90             : 
      91        2354 :     if ( p->GetObject().is() )
      92             :     {
      93        2324 :         p->GetObject()->addStateChangeListener( xRet );
      94             : 
      95        2324 :         uno::Reference < util::XCloseable > xClose( p->GetObject(), uno::UNO_QUERY );
      96             :         DBG_ASSERT( xClose.is(), "Object does not support XCloseable!" );
      97        2324 :         if ( xClose.is() )
      98        2324 :             xClose->addCloseListener( xRet );
      99             : 
     100        4648 :         uno::Reference < document::XEventBroadcaster > xBrd( p->GetObject(), uno::UNO_QUERY );
     101        2324 :         if ( xBrd.is() )
     102        2324 :             xBrd->addEventListener( xRet );
     103             : 
     104        2324 :         xRet->nState = p->GetObject()->getCurrentState();
     105        2324 :         if ( xRet->nState == embed::EmbedStates::RUNNING )
     106             :         {
     107        2054 :             uno::Reference < util::XModifiable > xMod( p->GetObject()->getComponent(), uno::UNO_QUERY );
     108        2054 :             if ( xMod.is() )
     109             :                 // listen for changes in running state (update replacements in case of changes)
     110        2050 :                 xMod->addModifyListener( xRet );
     111        2324 :         }
     112             :     }
     113             : 
     114        2354 :     return xRet;
     115             : }
     116             : 
     117         608 : void SAL_CALL EmbedEventListener_Impl::changingState( const lang::EventObject&,
     118             :                                                     ::sal_Int32,
     119             :                                                     ::sal_Int32 )
     120             :     throw ( embed::WrongStateException,
     121             :             uno::RuntimeException, std::exception )
     122             : {
     123         608 : }
     124             : 
     125         596 : void SAL_CALL EmbedEventListener_Impl::stateChanged( const lang::EventObject&,
     126             :                                                     ::sal_Int32 nOldState,
     127             :                                                     ::sal_Int32 nNewState )
     128             :     throw ( uno::RuntimeException, std::exception )
     129             : {
     130         596 :     SolarMutexGuard aGuard;
     131         596 :     nState = nNewState;
     132         596 :     if ( !pObject )
     133         596 :         return;
     134             : 
     135        1192 :     uno::Reference < util::XModifiable > xMod( pObject->GetObject()->getComponent(), uno::UNO_QUERY );
     136         596 :     if ( nNewState == embed::EmbedStates::RUNNING )
     137             :     {
     138             :         // TODO/LATER: container must be set before!
     139             :         // When is this event created? Who sets the new container when it changed?
     140         238 :         if( ( pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON ) && nOldState != embed::EmbedStates::LOADED && !pObject->IsChart() )
     141             :             // get new replacement after deactivation
     142           0 :             pObject->UpdateReplacement();
     143             : 
     144         238 :         if( pObject->IsChart() && nOldState == embed::EmbedStates::UI_ACTIVE )
     145             :         {
     146             :             //create a new metafile replacement when leaving the edit mode
     147             :             //for buggy documents where the old image looks different from the correct one
     148           2 :             if( xMod.is() && !xMod->isModified() )//in case of modification a new replacement will be requested anyhow
     149           0 :                 pObject->UpdateReplacementOnDemand();
     150             :         }
     151             : 
     152         238 :         if ( xMod.is() && nOldState == embed::EmbedStates::LOADED )
     153             :             // listen for changes (update replacements in case of changes)
     154         236 :             xMod->addModifyListener( this );
     155             :     }
     156         358 :     else if ( nNewState == embed::EmbedStates::LOADED )
     157             :     {
     158             :         // in loaded state we can't listen
     159         356 :         if ( xMod.is() )
     160           0 :             xMod->removeModifyListener( this );
     161         596 :     }
     162             : }
     163             : 
     164       13631 : void SAL_CALL EmbedEventListener_Impl::modified( const lang::EventObject& ) throw (uno::RuntimeException, std::exception)
     165             : {
     166       13631 :     SolarMutexGuard aGuard;
     167       13631 :     if ( pObject && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON )
     168             :     {
     169       10988 :         if ( nState == embed::EmbedStates::RUNNING )
     170             :         {
     171             :             // updates only necessary in non-active states
     172       10966 :             if( pObject->IsChart() )
     173        1236 :                 pObject->UpdateReplacementOnDemand();
     174             :             else
     175        9730 :                 pObject->UpdateReplacement();
     176             :         }
     177          44 :         else if ( nState == embed::EmbedStates::ACTIVE ||
     178          22 :                   nState == embed::EmbedStates::UI_ACTIVE ||
     179           0 :                   nState == embed::EmbedStates::INPLACE_ACTIVE )
     180             :         {
     181             :             // in case the object is inplace or UI active the replacement image should be updated on demand
     182          22 :             pObject->UpdateReplacementOnDemand();
     183             :         }
     184       13631 :     }
     185       13631 : }
     186             : 
     187       18554 : void SAL_CALL EmbedEventListener_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException, std::exception )
     188             : {
     189       18554 :     SolarMutexGuard aGuard;
     190             : 
     191       18554 :     if ( pObject && aEvent.EventName == "OnVisAreaChanged" && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON && !pObject->IsChart() )
     192             :     {
     193           8 :         pObject->UpdateReplacement();
     194       18554 :     }
     195       18554 : }
     196             : 
     197         422 : void SAL_CALL EmbedEventListener_Impl::queryClosing( const lang::EventObject& Source, sal_Bool )
     198             :         throw ( util::CloseVetoException, uno::RuntimeException, std::exception)
     199             : {
     200             :     // An embedded object can be shared between several objects (f.e. for undo purposes)
     201             :     // the object will not be closed before the last "customer" is destroyed
     202             :     // Now the EmbeddedObjectRef helper class works like a "lock" on the object
     203         422 :     if ( pObject && pObject->IsLocked() && Source.Source == pObject->GetObject() )
     204         422 :         throw util::CloseVetoException();
     205           0 : }
     206             : 
     207           0 : void SAL_CALL EmbedEventListener_Impl::notifyClosing( const lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException, std::exception)
     208             : {
     209           0 :     if ( pObject && Source.Source == pObject->GetObject() )
     210             :     {
     211           0 :         pObject->Clear();
     212           0 :         pObject = 0;
     213             :     }
     214           0 : }
     215             : 
     216        2286 : void SAL_CALL EmbedEventListener_Impl::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException, std::exception )
     217             : {
     218        2286 :     if ( pObject && aEvent.Source == pObject->GetObject() )
     219             :     {
     220           0 :         pObject->Clear();
     221           0 :         pObject = 0;
     222             :     }
     223        2286 : }
     224             : 
     225             : struct EmbeddedObjectRef_Impl
     226             : {
     227             :     uno::Reference <embed::XEmbeddedObject> mxObj;
     228             : 
     229             :     EmbedEventListener_Impl*                    xListener;
     230             :     OUString                             aPersistName;
     231             :     OUString                             aMediaType;
     232             :     comphelper::EmbeddedObjectContainer*        pContainer;
     233             :     Graphic*                                    pGraphic;
     234             :     sal_Int64                                   nViewAspect;
     235             :     bool                                        bIsLocked:1;
     236             :     bool                                        bNeedUpdate:1;
     237             : 
     238             :     // #i104867#
     239             :     sal_uInt32                                  mnGraphicVersion;
     240             :     awt::Size                                   aDefaultSizeForChart_In_100TH_MM;//#i103460# charts do not necessaryly have an own size within ODF files, in this case they need to use the size settings from the surrounding frame, which is made available with this member
     241             : 
     242        1462 :     EmbeddedObjectRef_Impl() :
     243             :         xListener(0),
     244             :         pContainer(NULL),
     245             :         pGraphic(NULL),
     246             :         nViewAspect(embed::Aspects::MSOLE_CONTENT),
     247             :         bIsLocked(false),
     248             :         bNeedUpdate(false),
     249             :         mnGraphicVersion(0),
     250        1462 :         aDefaultSizeForChart_In_100TH_MM(awt::Size(8000,7000))
     251        1462 :     {}
     252             : 
     253         872 :     EmbeddedObjectRef_Impl( const EmbeddedObjectRef_Impl& r ) :
     254             :         mxObj(r.mxObj),
     255             :         xListener(0),
     256             :         aPersistName(r.aPersistName),
     257             :         aMediaType(r.aMediaType),
     258             :         pContainer(r.pContainer),
     259             :         pGraphic(NULL),
     260             :         nViewAspect(r.nViewAspect),
     261             :         bIsLocked(r.bIsLocked),
     262             :         bNeedUpdate(r.bNeedUpdate),
     263             :         mnGraphicVersion(0),
     264         872 :         aDefaultSizeForChart_In_100TH_MM(r.aDefaultSizeForChart_In_100TH_MM)
     265             :     {
     266         872 :         if (r.pGraphic && !r.bNeedUpdate)
     267         572 :             pGraphic = new Graphic(*r.pGraphic);
     268         872 :     }
     269             : 
     270        2334 :     ~EmbeddedObjectRef_Impl()
     271        2334 :     {
     272        2334 :         delete pGraphic;
     273        2334 :     }
     274             : };
     275             : 
     276       18612 : const uno::Reference <embed::XEmbeddedObject>& EmbeddedObjectRef::operator->() const
     277             : {
     278       18612 :     return mpImpl->mxObj;
     279             : }
     280             : 
     281       39481 : const uno::Reference <embed::XEmbeddedObject>& EmbeddedObjectRef::GetObject() const
     282             : {
     283       39481 :     return mpImpl->mxObj;
     284             : }
     285             : 
     286        1214 : EmbeddedObjectRef::EmbeddedObjectRef() : mpImpl(new EmbeddedObjectRef_Impl) {}
     287             : 
     288         248 : EmbeddedObjectRef::EmbeddedObjectRef( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Int64 nAspect ) :
     289         248 :     mpImpl(new EmbeddedObjectRef_Impl)
     290             : {
     291         248 :     mpImpl->nViewAspect = nAspect;
     292         248 :     mpImpl->mxObj = xObj;
     293         248 :     mpImpl->xListener = EmbedEventListener_Impl::Create( this );
     294         248 : }
     295             : 
     296         872 : EmbeddedObjectRef::EmbeddedObjectRef( const EmbeddedObjectRef& rObj ) :
     297         872 :     mpImpl(new EmbeddedObjectRef_Impl(*rObj.mpImpl))
     298             : {
     299         872 :     mpImpl->xListener = EmbedEventListener_Impl::Create( this );
     300         872 : }
     301             : 
     302        2334 : EmbeddedObjectRef::~EmbeddedObjectRef()
     303             : {
     304        2334 :     Clear();
     305        2334 :     delete mpImpl;
     306        2334 : }
     307             : 
     308        1234 : void EmbeddedObjectRef::Assign( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Int64 nAspect )
     309             : {
     310             :     DBG_ASSERT(!mpImpl->mxObj.is(), "Never assign an already assigned object!");
     311             : 
     312        1234 :     Clear();
     313        1234 :     mpImpl->nViewAspect = nAspect;
     314        1234 :     mpImpl->mxObj = xObj;
     315        1234 :     mpImpl->xListener = EmbedEventListener_Impl::Create( this );
     316             : 
     317             :     //#i103460#
     318        1234 :     if ( IsChart() )
     319             :     {
     320         478 :         uno::Reference < chart2::XDefaultSizeTransmitter > xSizeTransmitter( xObj, uno::UNO_QUERY );
     321             :         DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
     322         478 :         if( xSizeTransmitter.is() )
     323         478 :             xSizeTransmitter->setDefaultSize( mpImpl->aDefaultSizeForChart_In_100TH_MM );
     324             :     }
     325        1234 : }
     326             : 
     327        4514 : void EmbeddedObjectRef::Clear()
     328             : {
     329        4514 :     if (mpImpl->mxObj.is() && mpImpl->xListener)
     330             :     {
     331        2324 :         mpImpl->mxObj->removeStateChangeListener(mpImpl->xListener);
     332             : 
     333        2324 :         uno::Reference<util::XCloseable> xClose(mpImpl->mxObj, uno::UNO_QUERY);
     334        2324 :         if ( xClose.is() )
     335        2324 :             xClose->removeCloseListener( mpImpl->xListener );
     336             : 
     337        4648 :         uno::Reference<document::XEventBroadcaster> xBrd(mpImpl->mxObj, uno::UNO_QUERY);
     338        2324 :         if ( xBrd.is() )
     339        2324 :             xBrd->removeEventListener( mpImpl->xListener );
     340             : 
     341        2324 :         if ( mpImpl->bIsLocked )
     342             :         {
     343        1146 :             if ( xClose.is() )
     344             :             {
     345             :                 try
     346             :                 {
     347        1146 :                     mpImpl->mxObj->changeState(embed::EmbedStates::LOADED);
     348        1146 :                     xClose->close( true );
     349             :                 }
     350         172 :                 catch (const util::CloseVetoException&)
     351             :                 {
     352             :                     // there's still someone who needs the object!
     353             :                 }
     354           0 :                 catch (const uno::Exception&)
     355             :                 {
     356             :                     OSL_FAIL( "Error on switching of the object to loaded state and closing!\n" );
     357             :                 }
     358             :             }
     359             :         }
     360             : 
     361        2324 :         if ( mpImpl->xListener )
     362             :         {
     363        2324 :             mpImpl->xListener->pObject = 0;
     364        2324 :             mpImpl->xListener->release();
     365        2324 :             mpImpl->xListener = 0;
     366             :         }
     367             : 
     368        2324 :         mpImpl->mxObj = NULL;
     369        4648 :         mpImpl->bNeedUpdate = false;
     370             :     }
     371             : 
     372        4514 :     mpImpl->pContainer = 0;
     373        4514 :     mpImpl->bIsLocked = false;
     374        4514 :     mpImpl->bNeedUpdate = false;
     375        4514 : }
     376             : 
     377       25522 : bool EmbeddedObjectRef::is() const
     378             : {
     379       25522 :     return mpImpl->mxObj.is();
     380             : }
     381             : 
     382        1804 : void EmbeddedObjectRef::AssignToContainer( comphelper::EmbeddedObjectContainer* pContainer, const OUString& rPersistName )
     383             : {
     384        1804 :     mpImpl->pContainer = pContainer;
     385        1804 :     mpImpl->aPersistName = rPersistName;
     386             : 
     387        1804 :     if ( mpImpl->pGraphic && !mpImpl->bNeedUpdate && pContainer )
     388         562 :         SetGraphicToContainer( *mpImpl->pGraphic, *pContainer, mpImpl->aPersistName, OUString() );
     389        1804 : }
     390             : 
     391       10266 : comphelper::EmbeddedObjectContainer* EmbeddedObjectRef::GetContainer() const
     392             : {
     393       10266 :     return mpImpl->pContainer;
     394             : }
     395             : 
     396       20165 : sal_Int64 EmbeddedObjectRef::GetViewAspect() const
     397             : {
     398       20165 :     return mpImpl->nViewAspect;
     399             : }
     400             : 
     401         340 : void EmbeddedObjectRef::SetViewAspect( sal_Int64 nAspect )
     402             : {
     403         340 :     mpImpl->nViewAspect = nAspect;
     404         340 : }
     405             : 
     406        1872 : void EmbeddedObjectRef::Lock( bool bLock )
     407             : {
     408        1872 :     mpImpl->bIsLocked = bLock;
     409        1872 : }
     410             : 
     411         422 : bool EmbeddedObjectRef::IsLocked() const
     412             : {
     413         422 :     return mpImpl->bIsLocked;
     414             : }
     415             : 
     416        9750 : void EmbeddedObjectRef::GetReplacement( bool bUpdate )
     417             : {
     418        9750 :     if ( bUpdate )
     419             :     {
     420        9738 :         DELETEZ( mpImpl->pGraphic );
     421        9738 :         mpImpl->aMediaType = OUString();
     422        9738 :         mpImpl->pGraphic = new Graphic;
     423        9738 :         mpImpl->mnGraphicVersion++;
     424             :     }
     425          12 :     else if ( !mpImpl->pGraphic )
     426             :     {
     427          12 :         mpImpl->pGraphic = new Graphic;
     428          12 :         mpImpl->mnGraphicVersion++;
     429             :     }
     430             :     else
     431             :     {
     432             :         OSL_FAIL("No update, but replacement exists already!");
     433        9750 :         return;
     434             :     }
     435             : 
     436        9750 :     boost::scoped_ptr<SvStream> pGraphicStream(GetGraphicStream( bUpdate ));
     437        9750 :     if ( pGraphicStream )
     438             :     {
     439        9750 :         GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
     440        9750 :         if( mpImpl->pGraphic )
     441        9750 :             rGF.ImportGraphic( *mpImpl->pGraphic, OUString(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
     442        9750 :         mpImpl->mnGraphicVersion++;
     443        9750 :     }
     444             : }
     445             : 
     446         174 : const Graphic* EmbeddedObjectRef::GetGraphic( OUString* pMediaType ) const
     447             : {
     448             :     try
     449             :     {
     450         174 :         if ( mpImpl->bNeedUpdate )
     451             :             // bNeedUpdate will be set to false while retrieving new replacement
     452           0 :             const_cast < EmbeddedObjectRef* >(this)->GetReplacement(true);
     453         174 :         else if ( !mpImpl->pGraphic )
     454          12 :             const_cast < EmbeddedObjectRef* >(this)->GetReplacement(false);
     455             :     }
     456           0 :     catch( const uno::Exception& ex )
     457             :     {
     458             :         SAL_WARN("svtools.misc", "Something went wrong on getting the graphic: " << ex.Message);
     459             :     }
     460             : 
     461         174 :     if ( mpImpl->pGraphic && pMediaType )
     462           0 :         *pMediaType = mpImpl->aMediaType;
     463         174 :     return mpImpl->pGraphic;
     464             : }
     465             : 
     466         650 : Size EmbeddedObjectRef::GetSize( MapMode* pTargetMapMode ) const
     467             : {
     468         650 :     MapMode aSourceMapMode( MAP_100TH_MM );
     469         650 :     Size aResult;
     470             : 
     471         650 :     if ( mpImpl->nViewAspect == embed::Aspects::MSOLE_ICON )
     472             :     {
     473           0 :         const Graphic* pGraphic = GetGraphic();
     474           0 :         if ( pGraphic )
     475             :         {
     476           0 :             aSourceMapMode = pGraphic->GetPrefMapMode();
     477           0 :             aResult = pGraphic->GetPrefSize();
     478             :         }
     479             :         else
     480           0 :             aResult = Size( 2500, 2500 );
     481             :     }
     482             :     else
     483             :     {
     484         650 :         awt::Size aSize;
     485             : 
     486         650 :         if (mpImpl->mxObj.is())
     487             :         {
     488             :             try
     489             :             {
     490         650 :                 aSize = mpImpl->mxObj->getVisualAreaSize(mpImpl->nViewAspect);
     491             :             }
     492          40 :             catch(const embed::NoVisualAreaSizeException&)
     493             :             {
     494             :             }
     495           2 :             catch(const uno::Exception&)
     496             :             {
     497             :                 OSL_FAIL( "Something went wrong on getting of the size of the object!" );
     498             :             }
     499             : 
     500             :             try
     501             :             {
     502         650 :                 aSourceMapMode = VCLUnoHelper::UnoEmbed2VCLMapUnit(mpImpl->mxObj->getMapUnit(mpImpl->nViewAspect));
     503             :             }
     504           2 :             catch(const uno::Exception&)
     505             :             {
     506             :                 OSL_FAIL( "Can not get the map mode!" );
     507             :             }
     508             :         }
     509             : 
     510         650 :         if ( !aSize.Height && !aSize.Width )
     511             :         {
     512         216 :             aSize.Width = 5000;
     513         216 :             aSize.Height = 5000;
     514             :         }
     515             : 
     516         650 :         aResult = Size( aSize.Width, aSize.Height );
     517             :     }
     518             : 
     519         650 :     if ( pTargetMapMode )
     520         650 :         aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode );
     521             : 
     522         650 :     return aResult;
     523             : }
     524             : 
     525           0 : void EmbeddedObjectRef::SetGraphicStream( const uno::Reference< io::XInputStream >& xInGrStream,
     526             :                                             const OUString& rMediaType )
     527             : {
     528           0 :     if ( mpImpl->pGraphic )
     529           0 :         delete mpImpl->pGraphic;
     530           0 :     mpImpl->pGraphic = new Graphic();
     531           0 :     mpImpl->aMediaType = rMediaType;
     532           0 :     mpImpl->mnGraphicVersion++;
     533             : 
     534           0 :     boost::scoped_ptr<SvStream> pGraphicStream(::utl::UcbStreamHelper::CreateStream( xInGrStream ));
     535             : 
     536           0 :     if ( pGraphicStream )
     537             :     {
     538           0 :         GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
     539           0 :         rGF.ImportGraphic( *mpImpl->pGraphic, "", *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
     540           0 :         mpImpl->mnGraphicVersion++;
     541             : 
     542           0 :         if ( mpImpl->pContainer )
     543             :         {
     544           0 :             pGraphicStream->Seek( 0 );
     545           0 :             uno::Reference< io::XInputStream > xInSeekGrStream = new ::utl::OSeekableInputStreamWrapper( pGraphicStream.get() );
     546             : 
     547           0 :             mpImpl->pContainer->InsertGraphicStream( xInSeekGrStream, mpImpl->aPersistName, rMediaType );
     548             :         }
     549             :     }
     550             : 
     551           0 :     mpImpl->bNeedUpdate = false;
     552             : 
     553           0 : }
     554             : 
     555         146 : void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const OUString& rMediaType )
     556             : {
     557         146 :     if ( mpImpl->pGraphic )
     558           6 :         delete mpImpl->pGraphic;
     559         146 :     mpImpl->pGraphic = new Graphic( rGraphic );
     560         146 :     mpImpl->aMediaType = rMediaType;
     561         146 :     mpImpl->mnGraphicVersion++;
     562             : 
     563         146 :     if ( mpImpl->pContainer )
     564         104 :         SetGraphicToContainer( rGraphic, *mpImpl->pContainer, mpImpl->aPersistName, rMediaType );
     565             : 
     566         146 :     mpImpl->bNeedUpdate = false;
     567         146 : }
     568             : 
     569        9750 : SvStream* EmbeddedObjectRef::GetGraphicStream( bool bUpdate ) const
     570             : {
     571             :     DBG_ASSERT( bUpdate || mpImpl->pContainer, "Can't retrieve current graphic!" );
     572        9750 :     uno::Reference < io::XInputStream > xStream;
     573        9750 :     if ( mpImpl->pContainer && !bUpdate )
     574             :     {
     575             :         SAL_INFO( "svtools.misc", "getting stream from container" );
     576             :         // try to get graphic stream from container storage
     577          12 :         xStream = mpImpl->pContainer->GetGraphicStream(mpImpl->mxObj, &mpImpl->aMediaType);
     578          12 :         if ( xStream.is() )
     579             :         {
     580          12 :             const sal_Int32 nConstBufferSize = 32000;
     581          12 :             SvStream *pStream = new SvMemoryStream( 32000, 32000 );
     582             :             try
     583             :             {
     584          12 :                 sal_Int32 nRead=0;
     585          12 :                 uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
     586          12 :                 do
     587             :                 {
     588          12 :                     nRead = xStream->readBytes ( aSequence, nConstBufferSize );
     589          12 :                     pStream->Write( aSequence.getConstArray(), nRead );
     590             :                 }
     591             :                 while ( nRead == nConstBufferSize );
     592          12 :                 pStream->Seek(0);
     593          12 :                 return pStream;
     594             :             }
     595           0 :             catch (const uno::Exception& ex)
     596             :             {
     597             :                 SAL_WARN("svtools.misc", "discarding broken embedded object preview: " << ex.Message);
     598           0 :                 delete pStream;
     599           0 :                 xStream.clear();
     600             :             }
     601             :         }
     602             :     }
     603             : 
     604        9738 :     if ( !xStream.is() )
     605             :     {
     606             :         SAL_INFO( "svtools.misc", "getting stream from object" );
     607        9738 :         bool bUserAllowsLinkUpdate(true);
     608        9738 :         const comphelper::EmbeddedObjectContainer* pContainer = GetContainer();
     609             : 
     610        9738 :         if(pContainer)
     611             :         {
     612        1568 :             bUserAllowsLinkUpdate = pContainer->getUserAllowsLinkUpdate();
     613             :         }
     614             : 
     615        9738 :         if(bUserAllowsLinkUpdate)
     616             :         {
     617             :             // update wanted or no stream in container storage available
     618        9738 :             xStream = GetGraphicReplacementStream(mpImpl->nViewAspect, mpImpl->mxObj, &mpImpl->aMediaType);
     619             : 
     620        9738 :             if(xStream.is())
     621             :             {
     622        9738 :                 if (mpImpl->pContainer)
     623        1568 :                     mpImpl->pContainer->InsertGraphicStream(xStream,mpImpl->aPersistName,mpImpl->aMediaType);
     624             : 
     625        9738 :                 SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream );
     626        9738 :                 if (pResult && bUpdate)
     627        9738 :                     mpImpl->bNeedUpdate = false;
     628             : 
     629        9738 :                 return pResult;
     630             :             }
     631             :         }
     632             :     }
     633             : 
     634           0 :     return NULL;
     635             : }
     636             : 
     637           0 : void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle &rRect, const OUString &rText, OutputDevice *pOut )
     638             : {
     639           0 :     MapMode aMM( MAP_APPFONT );
     640           0 :     Size aAppFontSz = pOut->LogicToLogic( Size( 0, 8 ), &aMM, NULL );
     641           0 :     vcl::Font aFnt( OUString("Helvetica"), aAppFontSz );
     642           0 :     aFnt.SetTransparent( true );
     643           0 :     aFnt.SetColor( Color( COL_LIGHTRED ) );
     644           0 :     aFnt.SetWeight( WEIGHT_BOLD );
     645           0 :     aFnt.SetFamily( FAMILY_SWISS );
     646             : 
     647           0 :     pOut->Push();
     648           0 :     pOut->SetBackground();
     649           0 :     pOut->SetFont( aFnt );
     650             : 
     651           0 :     Point aPt;
     652             : 
     653             :     // Now scale text such that it fits in the rectangle
     654             :     // We start with the default size and decrease 1-AppFont
     655           0 :     for( sal_uInt16 i = 8; i > 2; i-- )
     656             :     {
     657           0 :         aPt.X() = (rRect.GetWidth()  - pOut->GetTextWidth( rText )) / 2;
     658           0 :         aPt.Y() = (rRect.GetHeight() - pOut->GetTextHeight()) / 2;
     659             : 
     660           0 :         bool bTiny = false;
     661           0 :         if( aPt.X() < 0 ) bTiny = true, aPt.X() = 0;
     662           0 :         if( aPt.Y() < 0 ) bTiny = true, aPt.Y() = 0;
     663           0 :         if( bTiny )
     664             :         {
     665             :             // decrease for small images
     666           0 :             aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) );
     667           0 :             pOut->SetFont( aFnt );
     668             :         }
     669             :         else
     670           0 :             break;
     671             :     }
     672             : 
     673           0 :     Bitmap aBmp( SvtResId( BMP_PLUGIN ) );
     674           0 :     long nHeight = rRect.GetHeight() - pOut->GetTextHeight();
     675           0 :     long nWidth = rRect.GetWidth();
     676           0 :     if(nHeight > 0 && nWidth > 0 && aBmp.GetSizePixel().Width() > 0)
     677             :     {
     678           0 :         aPt.Y() = nHeight;
     679           0 :         Point   aP = rRect.TopLeft();
     680           0 :         Size    aBmpSize = aBmp.GetSizePixel();
     681             :         // fit bitmap in
     682           0 :         if( nHeight * 10 / nWidth
     683           0 :           > aBmpSize.Height() * 10 / aBmpSize.Width() )
     684             :         {
     685             :             // adjust to the width
     686             :             // keep proportions
     687           0 :             long nH = nWidth * aBmpSize.Height() / aBmpSize.Width();
     688             :             // center
     689           0 :             aP.Y() += (nHeight - nH) / 2;
     690           0 :             nHeight = nH;
     691             :         }
     692             :         else
     693             :         {
     694             :             // adjust to the height
     695             :             // keep proportions
     696           0 :             long nW = nHeight * aBmpSize.Width() / aBmpSize.Height();
     697             :             // center
     698           0 :             aP.X() += (nWidth - nW) / 2;
     699           0 :             nWidth = nW;
     700             :         }
     701             : 
     702           0 :         pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp );
     703             :     }
     704             : 
     705           0 :     pOut->IntersectClipRegion( rRect );
     706           0 :     aPt += rRect.TopLeft();
     707           0 :     pOut->DrawText( aPt, rText );
     708           0 :     pOut->Pop();
     709           0 : }
     710             : 
     711           0 : void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut )
     712             : {
     713           0 :     GDIMetaFile * pMtf = pOut->GetConnectMetaFile();
     714           0 :     if( pMtf && pMtf->IsRecord() )
     715           0 :         return;
     716             : 
     717           0 :     pOut->Push();
     718           0 :     pOut->SetLineColor( Color( COL_BLACK ) );
     719             : 
     720           0 :     Size aPixSize = pOut->LogicToPixel( rRect.GetSize() );
     721           0 :     aPixSize.Width() -= 1;
     722           0 :     aPixSize.Height() -= 1;
     723           0 :     Point aPixViewPos = pOut->LogicToPixel( rRect.TopLeft() );
     724           0 :     sal_Int32 nMax = aPixSize.Width() + aPixSize.Height();
     725           0 :     for( sal_Int32 i = 5; i < nMax; i += 5 )
     726             :     {
     727           0 :         Point a1( aPixViewPos ), a2( aPixViewPos );
     728           0 :         if( i > aPixSize.Width() )
     729           0 :             a1 += Point( aPixSize.Width(), i - aPixSize.Width() );
     730             :         else
     731           0 :             a1 += Point( i, 0 );
     732           0 :         if( i > aPixSize.Height() )
     733           0 :             a2 += Point( i - aPixSize.Height(), aPixSize.Height() );
     734             :         else
     735           0 :             a2 += Point( 0, i );
     736             : 
     737           0 :         pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) );
     738             :     }
     739             : 
     740           0 :     pOut->Pop();
     741             : 
     742             : }
     743             : 
     744        2429 : bool EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj )
     745             : {
     746        2429 :     if ( !xEmbObj.is() )
     747           0 :         return false;
     748             : 
     749             :     try
     750             :     {
     751        2429 :         if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED )
     752         106 :             xEmbObj->changeState( embed::EmbedStates::RUNNING );
     753             :     }
     754          60 :     catch (const uno::Exception&)
     755             :     {
     756          30 :         return false;
     757             :     }
     758             : 
     759        2399 :     return true;
     760             : }
     761             : 
     762         696 : void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic,
     763             :                                                 comphelper::EmbeddedObjectContainer& aContainer,
     764             :                                                 const OUString& aName,
     765             :                                                 const OUString& aMediaType )
     766             : {
     767         696 :     SvMemoryStream aStream;
     768         696 :     aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
     769         696 :     if ( rGraphic.ExportNative( aStream ) )
     770             :     {
     771         696 :         aStream.Seek( 0 );
     772             : 
     773         696 :            uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream );
     774         696 :            aContainer.InsertGraphicStream( xStream, aName, aMediaType );
     775             :     }
     776             :     else
     777         696 :         OSL_FAIL( "Export of graphic is failed!\n" );
     778         696 : }
     779             : 
     780        9738 : uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream(
     781             :                                                                 sal_Int64 nViewAspect,
     782             :                                                                 const uno::Reference< embed::XEmbeddedObject >& xObj,
     783             :                                                                 OUString* pMediaType )
     784             :     throw()
     785             : {
     786        9738 :     return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType);
     787             : }
     788             : 
     789       14335 : bool EmbeddedObjectRef::IsChart(const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj)
     790             : {
     791       14335 :     SvGlobalName aObjClsId(xObj->getClassID());
     792       28670 :     if(
     793       57340 :         SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId
     794       28670 :         || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId
     795       28670 :         || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId
     796       71675 :         || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId)
     797             :     {
     798        3719 :         return true;
     799             :     }
     800             : 
     801       10616 :     return false;
     802             : }
     803             : 
     804         237 : bool EmbeddedObjectRef::IsGLChart(const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj)
     805             : {
     806         237 :     static const char* env = getenv("CHART_DUMMY_FACTORY");
     807         237 :     if (IsChart(xObj))
     808             :     {
     809         203 :         if (env)
     810           0 :             return true;
     811             : 
     812         203 :         uno::Reference< chart2::XChartDocument > xChartDoc(xObj->getComponent(), uno::UNO_QUERY);
     813         203 :         if (!xChartDoc.is())
     814           0 :             return false;
     815             : 
     816         203 :         return xChartDoc->isOpenGLChart();
     817             :     }
     818          34 :     return false;
     819             : }
     820             : 
     821        9738 : void EmbeddedObjectRef::UpdateReplacement()
     822             : {
     823        9738 :     GetReplacement( true );
     824        9738 : }
     825             : 
     826        1258 : void EmbeddedObjectRef::UpdateReplacementOnDemand()
     827             : {
     828        1258 :     DELETEZ( mpImpl->pGraphic );
     829        1258 :     mpImpl->bNeedUpdate = true;
     830        1258 :     mpImpl->mnGraphicVersion++;
     831             : 
     832        1258 :     if( mpImpl->pContainer )
     833             :     {
     834             :         //remove graphic from container thus a new up to date one is requested on save
     835        1098 :         mpImpl->pContainer->RemoveGraphicStream( mpImpl->aPersistName );
     836             :     }
     837        1258 : }
     838             : 
     839       14336 : bool EmbeddedObjectRef::IsChart() const
     840             : {
     841             :     //todo maybe for 3.0:
     842             :     //if the changes work good for chart
     843             :     //we should apply them for all own ole objects
     844             : 
     845             :     //#i83708# #i81857# #i79578# request an ole replacement image only if really necessary
     846             :     //as this call can be very expensive and does block the user interface as long at it takes
     847             : 
     848       14336 :     if (!mpImpl->mxObj.is())
     849         238 :         return false;
     850             : 
     851       14098 :     return EmbeddedObjectRef::IsChart(mpImpl->mxObj);
     852             : }
     853             : 
     854         229 : bool EmbeddedObjectRef::IsGLChart() const
     855             : {
     856         229 :     if (!mpImpl->mxObj.is())
     857           0 :         return false;
     858             : 
     859         229 :     return EmbeddedObjectRef::IsGLChart(mpImpl->mxObj);
     860             : }
     861             : 
     862             : // MT: Only used for getting accessible attributes, which are not localized
     863           0 : OUString EmbeddedObjectRef::GetChartType()
     864             : {
     865           0 :     OUString Style;
     866           0 :     if ( mpImpl->mxObj.is() )
     867             :     {
     868           0 :         if ( IsChart() )
     869             :         {
     870           0 :             if ( svt::EmbeddedObjectRef::TryRunningState( mpImpl->mxObj ) )
     871             :             {
     872           0 :                 uno::Reference< chart2::XChartDocument > xChart( mpImpl->mxObj->getComponent(), uno::UNO_QUERY );
     873           0 :                 if (xChart.is())
     874             :                 {
     875           0 :                     uno::Reference< chart2::XDiagram > xDiagram( xChart->getFirstDiagram());
     876           0 :                     if( ! xDiagram.is())
     877           0 :                         return OUString();
     878           0 :                     uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
     879           0 :                     uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
     880             :                     // IA2 CWS. Unused: int nCoordinateCount = aCooSysSeq.getLength();
     881           0 :                     bool bGetChartType = false;
     882           0 :                     for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
     883             :                     {
     884           0 :                         uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
     885           0 :                         uno::Sequence< uno::Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
     886           0 :                         int nDimesionCount = aCooSysSeq[nCooSysIdx]->getDimension();
     887           0 :                         if( nDimesionCount == 3 )
     888           0 :                             Style += "3D ";
     889             :                         else
     890           0 :                             Style += "2D ";
     891           0 :                         for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
     892             :                         {
     893           0 :                             OUString strChartType = aChartTypes[nCTIdx]->getChartType();
     894           0 :                             if (strChartType == "com.sun.star.chart2.AreaChartType")
     895             :                             {
     896           0 :                                 Style += "Areas";
     897           0 :                                 bGetChartType = true;
     898             :                             }
     899           0 :                             else if (strChartType == "com.sun.star.chart2.BarChartType")
     900             :                             {
     901           0 :                                 Style += "Bars";
     902           0 :                                 bGetChartType = true;
     903             :                             }
     904           0 :                             else if (strChartType == "com.sun.star.chart2.ColumnChartType")
     905             :                             {
     906           0 :                                 uno::Reference< beans::XPropertySet > xProp( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY );
     907           0 :                                 if( xProp.is())
     908             :                                 {
     909           0 :                                     bool bCurrent = false;
     910           0 :                                     if( xProp->getPropertyValue( OUString("SwapXAndYAxis") ) >>= bCurrent )
     911             :                                     {
     912           0 :                                         if (bCurrent)
     913           0 :                                             Style += "Bars";
     914             :                                         else
     915           0 :                                             Style += "Columns";
     916           0 :                                         bGetChartType = true;
     917             :                                     }
     918           0 :                                 }
     919             :                             }
     920           0 :                             else if (strChartType == "com.sun.star.chart2.LineChartType")
     921             :                             {
     922           0 :                                 Style += "Lines";
     923           0 :                                 bGetChartType = true;
     924             :                             }
     925           0 :                             else if (strChartType == "com.sun.star.chart2.ScatterChartType")
     926             :                             {
     927           0 :                                 Style += "XY Chart";
     928           0 :                                 bGetChartType = true;
     929             :                             }
     930           0 :                             else if (strChartType == "com.sun.star.chart2.PieChartType")
     931             :                             {
     932           0 :                                 Style += "Pies";
     933           0 :                                 bGetChartType = true;
     934             :                             }
     935           0 :                             else if (strChartType == "com.sun.star.chart2.NetChartType")
     936             :                             {
     937           0 :                                 Style += "Radar";
     938           0 :                                 bGetChartType = true;
     939             :                             }
     940           0 :                             else if (strChartType == "com.sun.star.chart2.CandleStickChartType")
     941             :                             {
     942           0 :                                 Style += "Candle Stick Chart";
     943           0 :                                 bGetChartType = true;
     944             :                             }
     945           0 :                             if (bGetChartType)
     946           0 :                                 return Style;
     947           0 :                         }
     948           0 :                     }
     949           0 :                 }
     950             :             }
     951             :         }
     952             :     }
     953           0 :     return Style;
     954             : }
     955             : 
     956             : // #i104867#
     957         164 : sal_uInt32 EmbeddedObjectRef::getGraphicVersion() const
     958             : {
     959         164 :     return mpImpl->mnGraphicVersion;
     960             : }
     961             : 
     962          70 : void EmbeddedObjectRef::SetDefaultSizeForChart( const Size& rSizeIn_100TH_MM )
     963             : {
     964             :     //#i103460# charts do not necessaryly have an own size within ODF files,
     965             :     //for this case they need to use the size settings from the surrounding frame,
     966             :     //which is made available with this method
     967             : 
     968          70 :     mpImpl->aDefaultSizeForChart_In_100TH_MM = awt::Size( rSizeIn_100TH_MM.getWidth(), rSizeIn_100TH_MM.getHeight() );
     969             : 
     970          70 :     uno::Reference<chart2::XDefaultSizeTransmitter> xSizeTransmitter(mpImpl->mxObj, uno::UNO_QUERY);
     971             :     DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
     972          70 :     if( xSizeTransmitter.is() )
     973          70 :         xSizeTransmitter->setDefaultSize( mpImpl->aDefaultSizeForChart_In_100TH_MM );
     974          70 : }
     975             : 
     976        1227 : } // namespace svt
     977             : 
     978             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10