cid#1607171 Data race condition
[LibreOffice.git] / sc / source / ui / undo / areasave.cxx
blob374ae9c8a63a7bf23f45f1399f0adfee18f19fa5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sfx2/linkmgr.hxx>
22 #include <areasave.hxx>
23 #include <arealink.hxx>
24 #include <document.hxx>
25 #include <documentlinkmgr.hxx>
26 #include <docsh.hxx>
28 ScAreaLinkSaver::ScAreaLinkSaver( const ScAreaLink& rSource ) :
29 aFileName ( rSource.GetFile() ),
30 aFilterName ( rSource.GetFilter() ),
31 aOptions ( rSource.GetOptions() ),
32 aSourceArea ( rSource.GetSource() ),
33 aDestArea ( rSource.GetDestArea() ),
34 nRefreshDelaySeconds ( rSource.GetRefreshDelaySeconds() ) // seconds
38 bool ScAreaLinkSaver::IsEqualSource( const ScAreaLink& rCompare ) const
40 return ( aFileName == rCompare.GetFile() &&
41 aFilterName == rCompare.GetFilter() &&
42 aOptions == rCompare.GetOptions() &&
43 aSourceArea == rCompare.GetSource() &&
44 nRefreshDelaySeconds == rCompare.GetRefreshDelaySeconds() );
47 bool ScAreaLinkSaver::IsEqual( const ScAreaLink& rCompare ) const
49 return ( IsEqualSource( rCompare ) &&
50 aDestArea == rCompare.GetDestArea() );
53 void ScAreaLinkSaver::WriteToLink( ScAreaLink& rLink ) const
55 rLink.SetDestArea( aDestArea );
58 void ScAreaLinkSaver::InsertNewLink( ScDocument* pDoc )
60 // (see ScUndoRemoveAreaLink::Undo)
62 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
63 ScDocShell* pObjSh = pDoc->GetDocumentShell();
65 if ( pLinkManager && pObjSh )
67 ScAreaLink* pLink = new ScAreaLink( pObjSh, aFileName, aFilterName, aOptions,
68 aSourceArea, ScRange(aDestArea.aStart), nRefreshDelaySeconds );
69 pLink->SetInCreate( true );
70 pLink->SetDestArea( aDestArea );
71 OUString aTmp1(aFilterName), aTmp2(aSourceArea);
72 pLinkManager->InsertFileLink( *pLink, sfx2::SvBaseLinkObjectType::ClientFile, aFileName, &aTmp1, &aTmp2 );
73 pLink->Update();
74 pLink->SetInCreate( false );
78 ScAreaLinkSaveCollection::ScAreaLinkSaveCollection() {}
80 ScAreaLinkSaveCollection::~ScAreaLinkSaveCollection() {}
82 bool ScAreaLinkSaveCollection::IsEqual( const ScDocument* pDoc ) const
84 // IsEqual can be checked in sequence.
85 // Neither ref-update nor removing links will change the order.
87 const sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
88 if (pLinkManager)
90 size_t nPos = 0;
91 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
92 sal_uInt16 nLinkCount = rLinks.size();
93 for (sal_uInt16 i=0; i<nLinkCount; i++)
95 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
96 if (auto pAreaLink = dynamic_cast<ScAreaLink*>( pBase))
98 if ( nPos >= size() || !(*this)[nPos].IsEqual( *pAreaLink ) )
99 return false;
101 ++nPos;
104 if ( nPos < size() )
105 return false; // fewer links in the document than in the save collection
108 return true;
111 static ScAreaLink* lcl_FindLink( const ::sfx2::SvBaseLinks& rLinks, const ScAreaLinkSaver& rSaver )
113 sal_uInt16 nLinkCount = rLinks.size();
114 for (sal_uInt16 i=0; i<nLinkCount; i++)
116 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
117 if ( auto pAreaLink = dynamic_cast<ScAreaLink*>( pBase) )
118 if ( rSaver.IsEqualSource( *pAreaLink ) )
119 return pAreaLink; // found
121 return nullptr; // not found
124 void ScAreaLinkSaveCollection::Restore( ScDocument* pDoc )
126 // The save collection may contain additional entries that are not in the document.
127 // They must be inserted again.
128 // Entries from the save collection must be searched via source data, as the order
129 // of links changes if deleted entries are re-added to the link manager (always at the end).
131 sfx2::LinkManager* pLinkManager = pDoc->GetDocLinkManager().getLinkManager(false);
132 if (!pLinkManager)
133 return;
135 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
136 size_t nSaveCount = size();
137 for (size_t nPos=0; nPos<nSaveCount; ++nPos)
139 ScAreaLinkSaver& rSaver = (*this)[nPos];
140 ScAreaLink* pLink = lcl_FindLink( rLinks, rSaver );
141 if ( pLink )
142 rSaver.WriteToLink( *pLink ); // restore output position
143 else
144 rSaver.InsertNewLink( pDoc ); // re-insert deleted link
148 std::unique_ptr<ScAreaLinkSaveCollection> ScAreaLinkSaveCollection::CreateFromDoc( const ScDocument* pDoc )
150 std::unique_ptr<ScAreaLinkSaveCollection> pColl;
152 sfx2::LinkManager* pLinkManager = const_cast<ScDocument*>(pDoc)->GetLinkManager();
153 if (pLinkManager)
155 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
156 sal_uInt16 nLinkCount = rLinks.size();
157 for (sal_uInt16 i=0; i<nLinkCount; i++)
159 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
160 if (auto pAreaLink = dynamic_cast<ScAreaLink*>( pBase))
162 if (!pColl)
163 pColl.reset(new ScAreaLinkSaveCollection);
165 pColl->push_back( ScAreaLinkSaver( *pAreaLink ) );
170 return pColl;
173 ScAreaLinkSaver& ScAreaLinkSaveCollection::operator [](size_t nIndex)
175 return maData[nIndex];
178 const ScAreaLinkSaver& ScAreaLinkSaveCollection::operator [](size_t nIndex) const
180 return maData[nIndex];
183 size_t ScAreaLinkSaveCollection::size() const
185 return maData.size();
188 void ScAreaLinkSaveCollection::push_back(const ScAreaLinkSaver& p)
190 maData.push_back(p);
193 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */