slideshow/source/engine/slide/shapemanagerimpl.cxx |  136 ++++++++++++++++-----
 slideshow/source/engine/slide/shapemanagerimpl.hxx |   56 +++++++-
 slideshow/source/engine/slide/slideimpl.cxx        |   40 +-----
 3 files changed, 167 insertions(+), 65 deletions(-)

New commits:
commit c4f5e1e9d1984fc3d3ca689a5615d9ead92a7bd6
Author: Michael Jaumann <meta_...@yahoo.com>
Date:   Fri Mar 6 10:40:23 2015 +0000

    shape maps from LayerManager
    
    moved maps/ functionality to ShapeManager
    
    Change-Id: Iadb2c6f1b090b7ac384cb66c03fd5667e6c6971c

diff --git a/slideshow/source/engine/slide/shapemanagerimpl.cxx 
b/slideshow/source/engine/slide/shapemanagerimpl.cxx
index 71fc7f1..f364b2d 100644
--- a/slideshow/source/engine/slide/shapemanagerimpl.cxx
+++ b/slideshow/source/engine/slide/shapemanagerimpl.cxx
@@ -40,6 +40,9 @@ ShapeManagerImpl::ShapeManagerImpl( EventMultiplexer&         
   rMultiplexer,
                                     CursorManager&               
rCursorManager,
                                     const ShapeEventListenerMap& 
rGlobalListenersMap,
                                     const ShapeCursorMap&        
rGlobalCursorMap ):
+    maXShapeHash( 101 ),
+    maAllShapes(),
+    maUpdateShapes(),
     mrMultiplexer(rMultiplexer),
     mrCursorManager(rCursorManager),
     mrGlobalListenersMap(rGlobalListenersMap),
@@ -288,10 +291,14 @@ void ShapeManagerImpl::notifyShapeUpdate( const 
ShapeSharedPtr& rShape )
 
 ShapeSharedPtr ShapeManagerImpl::lookupShape( uno::Reference< drawing::XShape 
> const & xShape ) const
 {
-   /* if( mpLayerManager )
-        return mpLayerManager->lookupShape(xShape);*/
+    ENSURE_OR_THROW( xShape.is(), "LayerManager::lookupShape(): invalid Shape" 
);
 
-    return ShapeSharedPtr();
+    const XShapeHash::const_iterator aIter( maXShapeHash.find( xShape ));
+    if( aIter == maXShapeHash.end() )
+       return ShapeSharedPtr(); // not found
+
+    // found, return data part of entry pair.
+    return aIter->second;
 }
 
 void ShapeManagerImpl::addHyperlinkArea( const HyperlinkAreaSharedPtr& rArea )
@@ -375,6 +382,54 @@ bool ShapeManagerImpl::listenerAdded(
     return true;
 }
 
+void ShapeManagerImpl::implAddShape( const ShapeSharedPtr& rShape )
+{
+    ENSURE_OR_THROW( rShape, "ShapeManagerImpl::implAddShape(): invalid Shape" 
);
+
+    LayerShapeMap::value_type aValue (rShape, LayerWeakPtr());
+
+    OSL_ASSERT( maAllShapes.find(rShape) == maAllShapes.end() ); // shape must 
not be added already
+
+    maAllShapes.insert(aValue);
+
+    // update shape, it's just added and not yet painted
+    if( rShape->isVisible() )
+        notifyShapeUpdate( rShape );
+}
+
+void ShapeManagerImpl::implRemoveShape( const ShapeSharedPtr& rShape )
+{
+    ENSURE_OR_THROW( rShape, "ShapeManagerImpl::implRemoveShape(): invalid 
Shape" );
+
+    const LayerShapeMap::iterator aShapeEntry( maAllShapes.find(rShape) );
+
+    if( aShapeEntry == maAllShapes.end() )
+        return;
+
+    const bool bShapeUpdateNotified = maUpdateShapes.erase( rShape ) != 0;
+
+    // Enter shape area to the update area, but only if shape
+    // is visible and not in sprite mode (otherwise, updating
+    // the area doesn't do actual harm, but costs time)
+    // Actually, also add it if it was listed in
+    // maUpdateShapes (might have just gone invisible).
+    if( bShapeUpdateNotified ||
+        (rShape->isVisible() &&
+         !rShape->isBackgroundDetached()) )
+    {
+        LayerSharedPtr pLayer = aShapeEntry->second.lock();
+        if( pLayer )
+        {
+            // store area early, once the shape is removed from
+            // the layers, it no longer has any view references
+            pLayer->addUpdateRange( rShape->getUpdateArea() );
+        }
+    }
+
+    rShape->clearAllViewLayers();
+    maAllShapes.erase( aShapeEntry );
+}
+
 bool ShapeManagerImpl::listenerRemoved(
     const uno::Reference<presentation::XShapeEventListener>& /*xListener*/,
     const uno::Reference<drawing::XShape>&                   xShape )
diff --git a/slideshow/source/engine/slide/shapemanagerimpl.hxx 
b/slideshow/source/engine/slide/shapemanagerimpl.hxx
index 4f5f2f1..05d94e2 100644
--- a/slideshow/source/engine/slide/shapemanagerimpl.hxx
+++ b/slideshow/source/engine/slide/shapemanagerimpl.hxx
@@ -88,8 +88,20 @@ public:
 
     virtual void dispose() SAL_OVERRIDE;
 
+    virtual ShapeSharedPtr lookupShape(
+        ::com::sun::star::uno::Reference<
+           ::com::sun::star::drawing::XShape > const & xShape ) const 
SAL_OVERRIDE;
+
 private:
 
+    class ShapeComparator
+    {
+    public:
+        bool operator() (const ShapeSharedPtr& rpS1, const ShapeSharedPtr& 
rpS2 ) const
+        {
+            return Shape::lessThanShape::compare(rpS1.get(), rpS2.get());
+        }
+    };
     // MouseEventHandler interface
 
 
@@ -121,9 +133,7 @@ private:
     virtual void enterAnimationMode( const AnimatableShapeSharedPtr& rShape ) 
SAL_OVERRIDE;
     virtual void leaveAnimationMode( const AnimatableShapeSharedPtr& rShape ) 
SAL_OVERRIDE;
     virtual void notifyShapeUpdate( const ShapeSharedPtr& rShape ) 
SAL_OVERRIDE;
-    virtual ShapeSharedPtr lookupShape(
-        ::com::sun::star::uno::Reference<
-           ::com::sun::star::drawing::XShape > const & xShape ) const 
SAL_OVERRIDE;
+
     virtual void addHyperlinkArea( const boost::shared_ptr<HyperlinkArea>& 
rArea ) SAL_OVERRIDE;
     virtual void removeHyperlinkArea( const boost::shared_ptr<HyperlinkArea>& 
rArea ) SAL_OVERRIDE;
 
@@ -166,10 +176,19 @@ private:
                                    ::com::sun::star::drawing::XShape>&   
xShape,
                                 sal_Int16                                
nCursor );
 
+    /** Common stuff when adding a shape
+     */
+    void          implAddShape( const ShapeSharedPtr& rShape );
+
+    /** Common stuff when removing a shape
+     */
+    void          implRemoveShape( const ShapeSharedPtr& rShape );
+
 
     OUString checkForHyperlink( ::basegfx::B2DPoint const& hitPos )const;
 
 
+    typedef ::std::set< ShapeSharedPtr > ShapeUpdateSet;
     typedef std::map<ShapeSharedPtr,
                      boost::shared_ptr< ::cppu::OInterfaceContainerHelper >,
                      Shape::lessThanShape>        ShapeToListenersMap;
@@ -177,11 +196,40 @@ private:
                        Shape::lessThanShape>      ShapeToCursorMap;
     typedef std::set<HyperlinkAreaSharedPtr,
                      HyperlinkArea::lessThanArea> AreaSet;
+    typedef ::std::map< ShapeSharedPtr, LayerWeakPtr, ShapeComparator > 
LayerShapeMap;
+    typedef std::unordered_map<
+        ::com::sun::star::uno::Reference<
+            ::com::sun::star::drawing::XShape >,
+        ShapeSharedPtr,
+        hash< ::com::sun::star::uno::Reference<
+              ::com::sun::star::drawing::XShape > > > XShapeHash;
 
     typedef ThreadUnsafeListenerContainer<
         IntrinsicAnimationEventHandlerSharedPtr,
         std::vector<IntrinsicAnimationEventHandlerSharedPtr> > 
ImplIntrinsicAnimationEventHandlers;
 
+    /** Contains all shapes with their XShape reference as the key
+     */
+    XShapeHash               maXShapeHash;
+
+    /** Set of shapes this ShapeManager own
+
+        Contains the same set of shapes as XShapeHash, but is
+        sorted in z order, for painting and layer
+        association. Set entries are enriched with two flags
+        for buffering animation enable/disable changes, and
+        shape update requests.
+    */
+    LayerShapeMap            maAllShapes;
+
+    /** Set of shapes that have requested an update
+
+        When a shape is member of this set, its maShapes entry
+        has bNeedsUpdate set to true. We maintain this
+        redundant information for faster update processing.
+     */
+    ShapeUpdateSet           maUpdateShapes;
+
     EventMultiplexer&                   mrMultiplexer;
     CursorManager&                      mrCursorManager;
     const ShapeEventListenerMap&        mrGlobalListenersMap;
diff --git a/slideshow/source/engine/slide/slideimpl.cxx 
b/slideshow/source/engine/slide/slideimpl.cxx
index 1db93e9..4c7f294 100644
--- a/slideshow/source/engine/slide/slideimpl.cxx
+++ b/slideshow/source/engine/slide/slideimpl.cxx
@@ -937,7 +937,7 @@ bool SlideImpl::applyInitialShapeAttributes(
 
         if( xShape.is() )
         {
-            ShapeSharedPtr pShape( /*mpLayerManager->lookupShape( xShape )*/ );
+            ShapeSharedPtr pShape( mpShapeManager->lookupShape( xShape) );
 
             if( !pShape )
             {
commit 2e79054b549aa5b55b8f1ac90c9b8d47fb2d3e97
Author: Michael Jaumann <meta_...@yahoo.com>
Date:   Fri Mar 6 09:10:50 2015 +0000

    removed LayerManager
    
    will be replaced by direct calls to shape,
    or moved to shapemanagerimpl/slideimpl
    
    Change-Id: Iae64ffe62e841f4de4a11a8e5c61e5a5f8c6e137

diff --git a/slideshow/source/engine/slide/shapemanagerimpl.cxx 
b/slideshow/source/engine/slide/shapemanagerimpl.cxx
index a8d3248..71fc7f1 100644
--- a/slideshow/source/engine/slide/shapemanagerimpl.cxx
+++ b/slideshow/source/engine/slide/shapemanagerimpl.cxx
@@ -37,12 +37,10 @@ namespace slideshow {
 namespace internal {
 
 ShapeManagerImpl::ShapeManagerImpl( EventMultiplexer&            rMultiplexer,
-                                    LayerManagerSharedPtr const& rLayerManager,
                                     CursorManager&               
rCursorManager,
                                     const ShapeEventListenerMap& 
rGlobalListenersMap,
                                     const ShapeCursorMap&        
rGlobalCursorMap ):
     mrMultiplexer(rMultiplexer),
-    mpLayerManager(rLayerManager),
     mrCursorManager(rCursorManager),
     mrGlobalListenersMap(rGlobalListenersMap),
     mrGlobalCursorMap(rGlobalCursorMap),
@@ -88,8 +86,8 @@ void ShapeManagerImpl::activate( bool bSlideBackgoundPainted )
                                         
o3tl::select2nd<ShapeCursorMap::value_type>(),
                                         _1 )));
 
-        if( mpLayerManager )
-            mpLayerManager->activate( bSlideBackgoundPainted );
+      /*  if( mpLayerManager )
+            mpLayerManager->activate( bSlideBackgoundPainted );*/
     }
 }
 
@@ -99,9 +97,6 @@ void ShapeManagerImpl::deactivate()
     {
         mbEnabled = false;
 
-        if( mpLayerManager )
-            mpLayerManager->deactivate();
-
         maShapeListenerMap.clear();
         maShapeCursorMap.clear();
 
@@ -119,7 +114,6 @@ void ShapeManagerImpl::dispose()
     maHyperlinkShapes.clear();
     maShapeCursorMap.clear();
     maShapeListenerMap.clear();
-    mpLayerManager.reset();
 }
 
 bool ShapeManagerImpl::handleMousePressed( awt::MouseEvent const& )
@@ -250,9 +244,8 @@ bool ShapeManagerImpl::handleMouseMoved( const 
awt::MouseEvent& e )
 
 bool ShapeManagerImpl::update()
 {
-    if( mbEnabled && mpLayerManager )
-        return mpLayerManager->update();
-
+    //if( mbEnabled)
+       // return mpLayerManager->update();
     return false;
 }
 
@@ -264,34 +257,39 @@ bool ShapeManagerImpl::update( ViewSharedPtr const& 
/*rView*/ )
 
 bool ShapeManagerImpl::needsUpdate() const
 {
-    if( mbEnabled && mpLayerManager )
-        return mpLayerManager->isUpdatePending();
+    //if( mbEnabled )
+       // return mpLayerManager->isUpdatePending();
 
     return false;
 }
 
 void ShapeManagerImpl::enterAnimationMode( const AnimatableShapeSharedPtr& 
rShape )
 {
-    if( mbEnabled && mpLayerManager )
-        mpLayerManager->enterAnimationMode(rShape);
+    if( mbEnabled)
+    {
+        ENSURE_OR_THROW( rShape, "ShapeManagerImpl::enterAnimationMode(): 
invalid Shape" );
+        rShape->enterAnimationMode();
+    }
 }
 
 void ShapeManagerImpl::leaveAnimationMode( const AnimatableShapeSharedPtr& 
rShape )
 {
-    if( mbEnabled && mpLayerManager )
-        mpLayerManager->leaveAnimationMode(rShape);
+    if( mbEnabled){
+        ENSURE_OR_THROW( rShape, "ShapeManagerImpl::leaveAnimationMode(): 
invalid Shape" );
+        rShape->leaveAnimationMode();
+    }
 }
 
 void ShapeManagerImpl::notifyShapeUpdate( const ShapeSharedPtr& rShape )
 {
-    if( mbEnabled && mpLayerManager )
-        mpLayerManager->notifyShapeUpdate(rShape);
+   // if( mbEnabled )
+       // mpLayerManager->notifyShapeUpdate(rShape);
 }
 
 ShapeSharedPtr ShapeManagerImpl::lookupShape( uno::Reference< drawing::XShape 
> const & xShape ) const
 {
-    if( mpLayerManager )
-        return mpLayerManager->lookupShape(xShape);
+   /* if( mpLayerManager )
+        return mpLayerManager->lookupShape(xShape);*/
 
     return ShapeSharedPtr();
 }
@@ -309,17 +307,46 @@ void ShapeManagerImpl::removeHyperlinkArea( const 
HyperlinkAreaSharedPtr& rArea
 AttributableShapeSharedPtr ShapeManagerImpl::getSubsetShape( const 
AttributableShapeSharedPtr& rOrigShape,
                                                              const 
DocTreeNode&                rTreeNode )
 {
-    if( mpLayerManager )
-        return mpLayerManager->getSubsetShape(rOrigShape,rTreeNode);
+    AttributableShapeSharedPtr pSubset;
+
+    // shape already added?
+    if( rOrigShape->createSubset( pSubset,
+                                  rTreeNode ) )
+    {
+        OSL_ENSURE( pSubset, "ShapeManagerImpl::getSubsetShape(): failed to 
create subset" );
+
+        // don't add to shape hash, we're dupes to the
+        // original XShape anyway - all subset shapes return
+        // the same XShape as the original one.
 
-    return AttributableShapeSharedPtr();
+        // add shape to corresponding layer
+        implAddShape( pSubset );
+
+        // update original shape, it now shows less content
+        // (the subset is removed from its displayed
+        // output). Subset shape is updated within
+        // implAddShape().
+        if( rOrigShape->isVisible() )
+            notifyShapeUpdate( rOrigShape );
+    }
+
+    return pSubset;
 }
 
 void ShapeManagerImpl::revokeSubset( const AttributableShapeSharedPtr& 
rOrigShape,
                                      const AttributableShapeSharedPtr& 
rSubsetShape )
 {
-    if( mpLayerManager )
-        mpLayerManager->revokeSubset(rOrigShape,rSubsetShape);
+    if( rOrigShape->revokeSubset( rSubsetShape ) )
+    {
+        OSL_ASSERT( maAllShapes.find(rSubsetShape) != maAllShapes.end() );
+
+        implRemoveShape( rSubsetShape );
+
+        // update original shape, it now shows more content
+        // (the subset is added back to its displayed output)
+        if( rOrigShape->isVisible() )
+            notifyShapeUpdate( rOrigShape );
+    }
 }
 
 bool ShapeManagerImpl::listenerAdded(
diff --git a/slideshow/source/engine/slide/shapemanagerimpl.hxx 
b/slideshow/source/engine/slide/shapemanagerimpl.hxx
index 6de066c..4f5f2f1 100644
--- a/slideshow/source/engine/slide/shapemanagerimpl.hxx
+++ b/slideshow/source/engine/slide/shapemanagerimpl.hxx
@@ -65,7 +65,6 @@ public:
         registeres its event handlers.
     */
     ShapeManagerImpl( EventMultiplexer&            rMultiplexer,
-                      LayerManagerSharedPtr const& rLayerManager,
                       CursorManager&               rCursorManager,
                       const ShapeEventListenerMap& rGlobalListenersMap,
                       const ShapeCursorMap&        rGlobalCursorMap );
@@ -184,7 +183,6 @@ private:
         std::vector<IntrinsicAnimationEventHandlerSharedPtr> > 
ImplIntrinsicAnimationEventHandlers;
 
     EventMultiplexer&                   mrMultiplexer;
-    LayerManagerSharedPtr               mpLayerManager;
     CursorManager&                      mrCursorManager;
     const ShapeEventListenerMap&        mrGlobalListenersMap;
     const ShapeCursorMap&               mrGlobalCursorMap;
diff --git a/slideshow/source/engine/slide/slideimpl.cxx 
b/slideshow/source/engine/slide/slideimpl.cxx
index 5549e5e..1db93e9 100644
--- a/slideshow/source/engine/slide/slideimpl.cxx
+++ b/slideshow/source/engine/slide/slideimpl.cxx
@@ -220,7 +220,6 @@ private:
     uno::Reference< drawing::XDrawPagesSupplier >       mxDrawPagesSupplier;
     uno::Reference< animations::XAnimationNode >        mxRootNode;
 
-    LayerManagerSharedPtr                               mpLayerManager;
     boost::shared_ptr<ShapeManagerImpl>                 mpShapeManager;
     boost::shared_ptr<SubsettableShapeManager>          
mpSubsettableShapeManager;
 
@@ -349,13 +348,8 @@ SlideImpl::SlideImpl( const uno::Reference< 
drawing::XDrawPage >&           xDra
     mxDrawPage( xDrawPage ),
     mxDrawPagesSupplier( xDrawPages ),
     mxRootNode( xRootNode ),
-    mpLayerManager( new LayerManager(
-                        rViewContainer,
-                        getSlideRect(),
-                        bDisableAnimationZOrder) ),
     mpShapeManager( new ShapeManagerImpl(
                         rEventMultiplexer,
-                        mpLayerManager,
                         rCursorManager,
                         rShapeListenerMap,
                         rShapeCursorMap)),
@@ -414,11 +408,6 @@ SlideImpl::~SlideImpl()
     {
         maContext.mrScreenUpdater.removeViewUpdate(mpShapeManager);
         mpShapeManager->dispose();
-
-        // TODO(Q3): Make sure LayerManager (and thus Shapes) dies
-        // first, because SlideShowContext has SubsettableShapeManager
-        // as reference member.
-        mpLayerManager.reset();
     }
 }
 
@@ -437,7 +426,7 @@ bool SlideImpl::show( bool bSlideBackgoundPainted )
     if( mbActive )
         return true; // already active
 
-    if( !mpShapeManager || !mpLayerManager )
+    if( !mpShapeManager)
         return false; // disposed
 
 
@@ -642,15 +631,10 @@ void SlideImpl::viewAdded( const UnoViewSharedPtr& rView )
     maSlideBitmaps.push_back(
         std::make_pair( rView,
                         VectorOfSlideBitmaps(SlideAnimationState_NUM_ENTRIES) 
));
-
-    if( mpLayerManager )
-        mpLayerManager->viewAdded( rView );
 }
 
 void SlideImpl::viewRemoved( const UnoViewSharedPtr& rView )
 {
-    if( mpLayerManager )
-        mpLayerManager->viewRemoved( rView );
 
     const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
     maSlideBitmaps.erase(
@@ -670,16 +654,13 @@ void SlideImpl::viewChanged( const UnoViewSharedPtr& 
rView )
 {
     // nothing to do for the Slide - getCurrentSlideBitmap() lazily
     // handles bitmap resizes
-    if( mbActive && mpLayerManager )
-        mpLayerManager->viewChanged(rView);
 }
 
 void SlideImpl::viewsChanged()
 {
     // nothing to do for the Slide - getCurrentSlideBitmap() lazily
     // handles bitmap resizes
-    if( mbActive && mpLayerManager )
-        mpLayerManager->viewsChanged();
+    if( mbActive);
 }
 
 bool SlideImpl::requestCursor( sal_Int16 nCursorShape )
@@ -708,8 +689,6 @@ SlideBitmapSharedPtr SlideImpl::createCurrentSlideBitmap( 
const UnoViewSharedPtr
 {
     ENSURE_OR_THROW( rView && rView->getCanvas(),
                       "SlideImpl::createCurrentSlideBitmap(): Invalid view" );
-    ENSURE_OR_THROW( mpLayerManager,
-                      "SlideImpl::createCurrentSlideBitmap(): Invalid layer 
manager" );
     ENSURE_OR_THROW( mbShowLoaded,
                       "SlideImpl::createCurrentSlideBitmap(): No show loaded" 
);
 
@@ -738,7 +717,6 @@ SlideBitmapSharedPtr SlideImpl::createCurrentSlideBitmap( 
const UnoViewSharedPtr
 
     // output all shapes to bitmap
     initSlideBackground( pBitmapCanvas, rBmpSize );
-    mpLayerManager->renderTo( pBitmapCanvas );
 
     return SlideBitmapSharedPtr( new SlideBitmap( pBitmap ) );
 }
@@ -782,8 +760,6 @@ bool SlideImpl::implPrefetchShow()
 
     ENSURE_OR_RETURN_FALSE( mxDrawPage.is(),
                        "SlideImpl::implPrefetchShow(): Invalid draw page" );
-    ENSURE_OR_RETURN_FALSE( mpLayerManager,
-                       "SlideImpl::implPrefetchShow(): Invalid layer manager" 
);
 
     // fetch desired page content
     // ==========================
@@ -961,7 +937,7 @@ bool SlideImpl::applyInitialShapeAttributes(
 
         if( xShape.is() )
         {
-            ShapeSharedPtr pShape( mpLayerManager->lookupShape( xShape ) );
+            ShapeSharedPtr pShape( /*mpLayerManager->lookupShape( xShape )*/ );
 
             if( !pShape )
             {
@@ -1040,8 +1016,6 @@ bool SlideImpl::loadShapes()
 
     ENSURE_OR_RETURN_FALSE( mxDrawPage.is(),
                        "SlideImpl::loadShapes(): Invalid draw page" );
-    ENSURE_OR_RETURN_FALSE( mpLayerManager,
-                       "SlideImpl::loadShapes(): Invalid layer manager" );
 
     // fetch desired page content
     // ==========================
@@ -1075,15 +1049,15 @@ bool SlideImpl::loadShapes()
                                                 0, /* shape num starts at 0 */
                                                 true );
 
-                mpLayerManager->addShape(
-                    aMPShapesFunctor.importBackgroundShape() );
+               /* mpLayerManager->addShape(
+                    aMPShapesFunctor.importBackgroundShape() );*/
 
                 while( !aMPShapesFunctor.isImportDone() )
                 {
                     ShapeSharedPtr const& rShape(
                         aMPShapesFunctor.importShape() );
                     if( rShape )
-                        mpLayerManager->addShape( rShape );
+                       /* mpLayerManager->addShape( rShape );*/;
                 }
                 addPolygons(aMPShapesFunctor.getPolygons());
 
@@ -1128,7 +1102,7 @@ bool SlideImpl::loadShapes()
             ShapeSharedPtr const& rShape(
                 aShapesFunctor.importShape() );
             if( rShape )
-                mpLayerManager->addShape( rShape );
+                /*mpLayerManager->addShape( rShape );*/;
         }
         addPolygons(aShapesFunctor.getPolygons());
     }
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to