LibreOffice Module sc (master)  1
servobj.cxx
Go to the documentation of this file.
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 <osl/thread.h>
21 #include <osl/diagnose.h>
22 #include <sot/exchange.hxx>
23 #include <sot/formats.hxx>
24 #include <sfx2/app.hxx>
25 #include <sfx2/linkmgr.hxx>
26 #include <servobj.hxx>
27 #include <docsh.hxx>
28 #include <impex.hxx>
29 #include <brdcst.hxx>
30 #include <rangenam.hxx>
31 #include <unotools/charclass.hxx>
32 
33 using namespace formula;
34 
35 static bool lcl_FillRangeFromName( ScRange& rRange, ScDocShell* pDocSh, const OUString& rName )
36 {
37  if (pDocSh)
38  {
39  ScDocument& rDoc = pDocSh->GetDocument();
40  ScRangeName* pNames = rDoc.GetRangeName();
41  if (pNames)
42  {
43  const ScRangeData* pData = pNames->findByUpperName(ScGlobal::getCharClassPtr()->uppercase(rName));
44  if (pData)
45  {
46  if ( pData->IsValidReference( rRange ) )
47  return true;
48  }
49  }
50  }
51  return false;
52 }
53 
55  ScServerObject* pObjP)
56  : pObj(pObjP)
57 {
58 }
59 
61 {
63 }
64 
66 {
67  pObj->Notify( aBroadcaster, rHint);
68 }
69 
70 ScServerObject::ScServerObject( ScDocShell* pShell, const OUString& rItem ) :
71  aForwarder( this ),
72  pDocSh( pShell ),
73  bRefreshListener( false )
74 {
75  // parse item string
76 
77  if ( lcl_FillRangeFromName( aRange, pDocSh, rItem ) )
78  {
79  aItemStr = rItem; // must be parsed again on ref update
80  }
81  else
82  {
83  // parse ref
84  ScDocument& rDoc = pDocSh->GetDocument();
86  aRange.aStart.SetTab( nTab );
87 
88  // For DDE link, we always must parse references using OOO A1 convention.
89 
90  if ( aRange.Parse( rItem, rDoc, FormulaGrammar::CONV_OOO ) & ScRefFlags::VALID )
91  {
92  // area reference
93  }
94  else if ( aRange.aStart.Parse( rItem, rDoc, FormulaGrammar::CONV_OOO ) & ScRefFlags::VALID )
95  {
96  // cell reference
98  }
99  else
100  {
101  OSL_FAIL("ScServerObject: invalid item");
102  }
103  }
104 
107 
108  StartListening(*pDocSh); // to notice if DocShell gets deleted
109  StartListening(*SfxGetpApp()); // for SfxHintId::ScAreasChanged
110 }
111 
113 {
114  Clear();
115 }
116 
118 {
119  if (pDocSh)
120  {
121  ScDocShell* pTemp = pDocSh;
122  pDocSh = nullptr;
123 
124  pTemp->GetDocument().EndListeningArea(aRange, false, &aForwarder);
125  pTemp->GetDocument().GetLinkManager()->RemoveServer( this );
126  EndListening(*pTemp);
128  }
129 }
130 
132 {
135 }
136 
138  css::uno::Any & rData /*out param*/,
139  const OUString & rMimeType, bool /* bSynchron */ )
140 {
141  if (!pDocSh)
142  return false;
143 
144  // named ranges may have changed -> update aRange
145  if ( !aItemStr.isEmpty() )
146  {
147  ScRange aNew;
148  if ( lcl_FillRangeFromName( aNew, pDocSh, aItemStr ) && aNew != aRange )
149  {
150  aRange = aNew;
151  bRefreshListener = true;
152  }
153  }
154 
155  if ( bRefreshListener )
156  {
157  // refresh the listeners now (this is called from a timer)
158 
159  EndListeningAll();
163  bRefreshListener = false;
164  }
165 
166  OUString aDdeTextFmt = pDocSh->GetDdeTextFmt();
167  ScDocument& rDoc = pDocSh->GetDocument();
168 
170  if (SotClipboardFormatId::STRING == eFormatId || SotClipboardFormatId::STRING_TSVC == eFormatId)
171  {
172  ScImportExport aObj( rDoc, aRange );
173  if( aDdeTextFmt[0] == 'F' )
174  aObj.SetFormulas( true );
175  if( aDdeTextFmt == "SYLK" || aDdeTextFmt == "FSYLK" )
176  {
177  OString aByteData;
178  if( aObj.ExportByteString( aByteData, osl_getThreadTextEncoding(), SotClipboardFormatId::SYLK ) )
179  {
180  rData <<= css::uno::Sequence< sal_Int8 >(
181  reinterpret_cast<const sal_Int8*>(aByteData.getStr()),
182  aByteData.getLength() + 1 );
183  return true;
184  }
185  return false;
186  }
187  if( aDdeTextFmt == "CSV" || aDdeTextFmt == "FCSV" )
188  aObj.SetSeparator( ',' );
189  /* TODO: STRING_TSVC could preserve line breaks with added quotes. */
191  return aObj.ExportData( rMimeType, rData );
192  }
193 
194  ScImportExport aObj( rDoc, aRange );
196  if( aObj.IsRef() )
197  return aObj.ExportData( rMimeType, rData );
198  return false;
199 }
200 
202 {
203  bool bDataChanged = false;
204 
205  // DocShell can't be tested via type info, because SfxHintId::Dying comes from the dtor
206  if ( &rBC == pDocSh )
207  {
208  // from DocShell, only SfxHintId::Dying is interesting
209  if ( rHint.GetId() == SfxHintId::Dying )
210  {
211  pDocSh = nullptr;
213  // don't access DocShell anymore for EndListening etc.
214  }
215  }
216  else if (dynamic_cast<const SfxApplication*>( &rBC) != nullptr)
217  {
218  if ( !aItemStr.isEmpty() && rHint.GetId() == SfxHintId::ScAreasChanged )
219  {
220  // check if named range was modified
221  ScRange aNew;
222  if ( lcl_FillRangeFromName( aNew, pDocSh, aItemStr ) && aNew != aRange )
223  bDataChanged = true;
224  }
225  }
226  else
227  {
228  // must be from Area broadcasters
229 
230  const ScHint* pScHint = dynamic_cast<const ScHint*>( &rHint );
231  if (pScHint && (pScHint->GetId() == SfxHintId::ScDataChanged))
232  bDataChanged = true;
233  else if (const ScAreaChangedHint *pChgHint = dynamic_cast<const ScAreaChangedHint*>(&rHint)) // position of broadcaster changed
234  {
235  const ScRange& aNewRange = pChgHint->GetRange();
236  if ( aRange != aNewRange )
237  {
238  bRefreshListener = true;
239  bDataChanged = true;
240  }
241  }
242  else
243  {
244  if (rHint.GetId() == SfxHintId::Dying)
245  {
246  // If the range is being deleted, listening must be restarted
247  // after the deletion is complete (done in GetData)
248  bRefreshListener = true;
249  bDataChanged = true;
250  }
251  }
252  }
253 
254  if ( bDataChanged && HasDataLinks() )
255  SvLinkSource::NotifyDataChanged();
256 }
257 
258 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScAddress aStart
Definition: address.hxx:500
virtual void Notify(const SfxHint &rHint) override
Definition: servobj.cxx:65
void Clear()
Definition: servobj.cxx:117
virtual ~ScServerObjectSvtListenerForwarder() override
Definition: servobj.cxx:60
std::unique_ptr< ContentProperties > pData
signed char sal_Int8
These options control how multi-line cells are converted during export in certain lossy formats (such...
Definition: impex.hxx:36
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:168
bool InsertServer(SvLinkSource *rObj)
ScAddress aEnd
Definition: address.hxx:501
ScDocShell * pDocSh
Definition: servobj.hxx:46
bool ExportData(const OUString &rMimeType, css::uno::Any &rValue)
Definition: impex.cxx:284
SfxHintId GetId() const
OUString aItemStr
Definition: servobj.hxx:48
SfxApplication * SfxGetpApp()
void RemoveServer(SvLinkSource *rObj)
const OUString & GetDdeTextFmt() const
Definition: docsh.hxx:367
void EndListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener)
Definition: documen7.cxx:61
SotClipboardFormatId
void EndListeningAll()
void SetTab(SCTAB nTabP)
Definition: address.hxx:283
SC_DLLPUBLIC ScRangeData * findByUpperName(const OUString &rName)
Definition: rangenam.cxx:682
void SetFormulas(bool b)
Definition: impex.hxx:118
bool ExportByteString(OString &, rtl_TextEncoding, SotClipboardFormatId)
Definition: impex.cxx:354
bool bRefreshListener
Definition: servobj.hxx:49
static bool lcl_FillRangeFromName(ScRange &rRange, ScDocShell *pDocSh, const OUString &rName)
Definition: servobj.cxx:35
ScServerObjectSvtListenerForwarder aForwarder
Definition: servobj.hxx:45
ScServerObject(ScDocShell *pShell, const OUString &rItem)
Definition: servobj.cxx:70
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
virtual bool GetData(css::uno::Any &rData, const OUString &rMimeType, bool bSynchron=false) override
Definition: servobj.cxx:137
bool IsRef() const
Definition: impex.hxx:100
bool HasDataLinks() const
void EndListeningAll()
ScRange aRange
Definition: servobj.hxx:47
static SotClipboardFormatId GetFormatIdFromMimeType(const OUString &rMimeType)
void SetExportTextOptions(const ScExportTextOptions &options)
Definition: impex.hxx:144
SC_DLLPUBLIC ScRefFlags Parse(const OUString &, const ScDocument &, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, ScAddress::ExternalInfo *pExtInfo=nullptr, const css::uno::Sequence< css::sheet::ExternalLinkInfo > *pExternalLinks=nullptr, const OUString *pErrRef=nullptr)
Definition: address.cxx:1733
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
static SC_DLLPUBLIC const CharClass * getCharClassPtr()
Definition: global.cxx:1010
const ScDocument & GetDocument() const
Definition: docsh.hxx:216
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: servobj.cxx:201
SC_DLLPUBLIC bool IsValidReference(ScRange &rRef) const
Definition: rangenam.cxx:385
void StartListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener)
Definition: documen7.cxx:35
SC_DLLPUBLIC ScRefFlags Parse(const OUString &, const ScDocument &, const Details &rDetails=detailsOOOa1, ExternalInfo *pExtInfo=nullptr, const css::uno::Sequence< css::sheet::ExternalLinkInfo > *pExternalLinks=nullptr, sal_Int32 *pSheetEndPos=nullptr, const OUString *pErrRef=nullptr)
Definition: address.cxx:1539
SC_DLLPUBLIC sfx2::LinkManager * GetLinkManager()
Definition: documen2.cxx:215
void EndListeningAll()
Definition: servobj.cxx:131
ScServerObjectSvtListenerForwarder(ScServerObject *pObjP)
Definition: servobj.cxx:54
static SCTAB GetCurTab()
Definition: docsh4.cxx:2547
virtual ~ScServerObject() override
Definition: servobj.cxx:112
sal_Int16 SCTAB
Definition: types.hxx:23
void SetSeparator(sal_Unicode c)
Definition: impex.hxx:116