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>
32
33using namespace formula;
34
35static 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::getCharClass().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
70ScServerObject::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
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
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: */
SfxApplication * SfxGetpApp()
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:1537
void SetTab(SCTAB nTabP)
Definition: address.hxx:295
const ScDocument & GetDocument() const
Definition: docsh.hxx:220
const OUString & GetDdeTextFmt() const
Definition: docsh.hxx:373
static SCTAB GetCurTab()
Definition: docsh4.cxx:2599
void EndListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener)
Definition: documen7.cxx:61
void StartListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener)
Definition: documen7.cxx:35
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:174
SC_DLLPUBLIC sfx2::LinkManager * GetLinkManager()
Definition: documen2.cxx:231
static SC_DLLPUBLIC const CharClass & getCharClass()
Definition: global.cxx:1062
void SetFormulas(bool b)
Definition: impex.hxx:134
bool ExportData(const OUString &rMimeType, css::uno::Any &rValue)
Definition: impex.cxx:287
bool ExportByteString(OString &, rtl_TextEncoding, SotClipboardFormatId)
Definition: impex.cxx:367
void SetExportTextOptions(const ScExportTextOptions &options)
Definition: impex.hxx:160
bool IsRef() const
Definition: impex.hxx:101
void SetSeparator(sal_Unicode c)
Definition: impex.hxx:132
SC_DLLPUBLIC ScRangeData * findByUpperName(const OUString &rName)
Definition: rangenam.cxx:704
ScAddress aEnd
Definition: address.hxx:498
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:1700
ScAddress aStart
Definition: address.hxx:497
virtual ~ScServerObjectSvtListenerForwarder() override
Definition: servobj.cxx:60
ScServerObjectSvtListenerForwarder(ScServerObject *pObjP)
Definition: servobj.cxx:54
virtual void Notify(const SfxHint &rHint) override
Definition: servobj.cxx:65
virtual bool GetData(css::uno::Any &rData, const OUString &rMimeType, bool bSynchron=false) override
Definition: servobj.cxx:137
ScRange aRange
Definition: servobj.hxx:46
void EndListeningAll()
Definition: servobj.cxx:131
virtual ~ScServerObject() override
Definition: servobj.cxx:112
bool bRefreshListener
Definition: servobj.hxx:48
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: servobj.cxx:201
OUString aItemStr
Definition: servobj.hxx:47
ScDocShell * pDocSh
Definition: servobj.hxx:45
void Clear()
Definition: servobj.cxx:117
ScServerObject(ScDocShell *pShell, const OUString &rItem)
Definition: servobj.cxx:70
ScServerObjectSvtListenerForwarder aForwarder
Definition: servobj.hxx:44
SfxHintId GetId() const
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
void EndListeningAll()
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
static SotClipboardFormatId GetFormatIdFromMimeType(const OUString &rMimeType)
void EndListeningAll()
bool InsertServer(SvLinkSource *rObj)
void RemoveServer(SvLinkSource *rObj)
bool HasDataLinks() const
SotClipboardFormatId
std::unique_ptr< sal_Int32[]> pData
static bool lcl_FillRangeFromName(ScRange &rRange, ScDocShell *pDocSh, const OUString &rName)
Definition: servobj.cxx:35
These options control how multi-line cells are converted during export in certain lossy formats (such...
Definition: impex.hxx:38
signed char sal_Int8
sal_Int16 SCTAB
Definition: types.hxx:22