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 : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
21 : #include <com/sun/star/document/XDocumentProperties.hpp>
22 :
23 : #include "scitems.hxx"
24 : #include "rangelst.hxx"
25 : #include <editeng/flstitem.hxx>
26 : #include <editeng/paperinf.hxx>
27 : #include <editeng/sizeitem.hxx>
28 : #include <rtl/strbuf.hxx>
29 : #include <sfx2/viewfrm.hxx>
30 : #include <sfx2/app.hxx>
31 : #include <sfx2/docfile.hxx>
32 : #include <sfx2/printer.hxx>
33 : #include <svx/postattr.hxx>
34 : #include <unotools/misccfg.hxx>
35 : #include <vcl/virdev.hxx>
36 : #include <vcl/msgbox.hxx>
37 :
38 : #include "docsh.hxx"
39 : #include "docshimp.hxx"
40 : #include "scmod.hxx"
41 : #include "tabvwsh.hxx"
42 : #include "viewdata.hxx"
43 : #include "docpool.hxx"
44 : #include "stlpool.hxx"
45 : #include "patattr.hxx"
46 : #include "uiitems.hxx"
47 : #include "hints.hxx"
48 : #include "docoptio.hxx"
49 : #include "viewopti.hxx"
50 : #include "pntlock.hxx"
51 : #include "chgtrack.hxx"
52 : #include "docfunc.hxx"
53 : #include "formulacell.hxx"
54 : #include "chgviset.hxx"
55 : #include "progress.hxx"
56 : #include "redcom.hxx"
57 : #include "sc.hrc"
58 : #include "inputopt.hxx"
59 : #include "drwlayer.hxx"
60 : #include "inputhdl.hxx"
61 : #include "conflictsdlg.hxx"
62 : #include "globstr.hrc"
63 : #include "markdata.hxx"
64 : #include <boost/scoped_ptr.hpp>
65 :
66 : // Redraw - Benachrichtigungen
67 :
68 0 : void ScDocShell::PostEditView( ScEditEngineDefaulter* pEditEngine, const ScAddress& rCursorPos )
69 : {
70 : // Broadcast( ScEditViewHint( pEditEngine, rCursorPos ) );
71 :
72 : // Test: nur aktive ViewShell
73 :
74 0 : ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
75 0 : if (pViewSh && pViewSh->GetViewData().GetDocShell() == this)
76 : {
77 0 : ScEditViewHint aHint( pEditEngine, rCursorPos );
78 0 : pViewSh->Notify( *this, aHint );
79 : }
80 0 : }
81 :
82 8060 : void ScDocShell::PostDataChanged()
83 : {
84 8060 : Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
85 8060 : SfxGetpApp()->Broadcast(SfxSimpleHint( FID_ANYDATACHANGED )); // Navigator
86 8060 : aDocument.ClearFormulaContext();
87 : //! Navigator direkt benachrichtigen!
88 8060 : }
89 :
90 10964 : void ScDocShell::PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
91 : SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, sal_uInt16 nPart,
92 : sal_uInt16 nExtFlags )
93 : {
94 10964 : ScRange aRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
95 10964 : PostPaint(aRange, nPart, nExtFlags);
96 10964 : }
97 :
98 17121 : void ScDocShell::PostPaint( const ScRangeList& rRanges, sal_uInt16 nPart, sal_uInt16 nExtFlags )
99 : {
100 17121 : ScRangeList aPaintRanges;
101 34242 : for (size_t i = 0, n = rRanges.size(); i < n; ++i)
102 : {
103 17121 : const ScRange& rRange = *rRanges[i];
104 17121 : SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
105 17121 : SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
106 17121 : SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
107 :
108 17121 : if (!ValidCol(nCol1)) nCol1 = MAXCOL;
109 17121 : if (!ValidRow(nRow1)) nRow1 = MAXROW;
110 17121 : if (!ValidCol(nCol2)) nCol2 = MAXCOL;
111 17121 : if (!ValidRow(nRow2)) nRow2 = MAXROW;
112 :
113 17121 : if ( pPaintLockData )
114 : {
115 : // #i54081# PAINT_EXTRAS still has to be broadcast because it changes the
116 : // current sheet if it's invalid. All other flags added to pPaintLockData.
117 8658 : sal_uInt16 nLockPart = nPart & ~PAINT_EXTRAS;
118 8658 : if ( nLockPart )
119 : {
120 : //! nExtFlags ???
121 : pPaintLockData->AddRange( ScRange( nCol1, nRow1, nTab1,
122 8501 : nCol2, nRow2, nTab2 ), nLockPart );
123 : }
124 :
125 8658 : nPart &= PAINT_EXTRAS; // for broadcasting
126 8658 : if (!nPart)
127 11512 : continue;
128 : }
129 :
130 11365 : if (nExtFlags & SC_PF_LINES) // Platz fuer Linien beruecksichtigen
131 : {
132 : //! Abfrage auf versteckte Spalten/Zeilen!
133 72 : if (nCol1>0) --nCol1;
134 72 : if (nCol2<MAXCOL) ++nCol2;
135 72 : if (nRow1>0) --nRow1;
136 72 : if (nRow2<MAXROW) ++nRow2;
137 : }
138 :
139 : // um zusammengefasste erweitern
140 11365 : if (nExtFlags & SC_PF_TESTMERGE)
141 6308 : aDocument.ExtendMerge( nCol1, nRow1, nCol2, nRow2, nTab1 );
142 :
143 11365 : if ( nCol1 != 0 || nCol2 != MAXCOL )
144 : {
145 : // Extend to whole rows if SC_PF_WHOLEROWS is set, or rotated or non-left
146 : // aligned cells are contained (see UpdatePaintExt).
147 : // Special handling for RTL text (#i9731#) is unnecessary now with full
148 : // support of right-aligned text.
149 :
150 13820 : if ( ( nExtFlags & SC_PF_WHOLEROWS ) ||
151 : aDocument.HasAttrib( nCol1,nRow1,nTab1,
152 6825 : MAXCOL,nRow2,nTab2, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
153 : {
154 251 : nCol1 = 0;
155 251 : nCol2 = MAXCOL;
156 : }
157 : }
158 11365 : aPaintRanges.Append(ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
159 : }
160 :
161 17121 : Broadcast(ScPaintHint(aPaintRanges.Combine(), nPart));
162 17121 : }
163 :
164 398 : void ScDocShell::PostPaintGridAll()
165 : {
166 398 : PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID );
167 398 : }
168 :
169 6299 : void ScDocShell::PostPaintCell( SCCOL nCol, SCROW nRow, SCTAB nTab )
170 : {
171 6299 : PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, SC_PF_TESTMERGE );
172 6299 : }
173 :
174 6299 : void ScDocShell::PostPaintCell( const ScAddress& rPos )
175 : {
176 6299 : PostPaintCell( rPos.Col(), rPos.Row(), rPos.Tab() );
177 6299 : }
178 :
179 235 : void ScDocShell::PostPaintExtras()
180 : {
181 235 : PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS );
182 235 : }
183 :
184 1201 : void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, const ScRange& rRange )
185 : {
186 1201 : if ( ( rExtFlags & SC_PF_LINES ) == 0 && aDocument.HasAttrib( rRange, HASATTR_PAINTEXT ) )
187 : {
188 : // If the range contains lines, shadow or conditional formats,
189 : // set SC_PF_LINES to include one extra cell in all directions.
190 :
191 43 : rExtFlags |= SC_PF_LINES;
192 : }
193 :
194 3427 : if ( ( rExtFlags & SC_PF_WHOLEROWS ) == 0 &&
195 2597 : ( rRange.aStart.Col() != 0 || rRange.aEnd.Col() != MAXCOL ) &&
196 974 : aDocument.HasAttrib( rRange, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
197 : {
198 : // If the range contains (logically) right- or center-aligned cells,
199 : // or rotated cells, set SC_PF_WHOLEROWS to paint the whole rows.
200 : // This test isn't needed after the cell changes, because it's also
201 : // tested in PostPaint. UpdatePaintExt may later be changed to do this
202 : // only if called before the changes.
203 :
204 187 : rExtFlags |= SC_PF_WHOLEROWS;
205 : }
206 1201 : }
207 :
208 145 : void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
209 : SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab )
210 : {
211 145 : UpdatePaintExt( rExtFlags, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ) );
212 145 : }
213 :
214 970 : void ScDocShell::LockPaint_Impl(bool bDoc)
215 : {
216 970 : if ( !pPaintLockData )
217 940 : pPaintLockData = new ScPaintLockData;
218 970 : pPaintLockData->IncLevel(bDoc);
219 970 : }
220 :
221 965 : void ScDocShell::UnlockPaint_Impl(bool bDoc)
222 : {
223 965 : if ( pPaintLockData )
224 : {
225 965 : if ( pPaintLockData->GetLevel(bDoc) )
226 964 : pPaintLockData->DecLevel(bDoc);
227 965 : if (!pPaintLockData->GetLevel(!bDoc) && !pPaintLockData->GetLevel(bDoc))
228 : {
229 : // Paint jetzt ausfuehren
230 :
231 936 : ScPaintLockData* pPaint = pPaintLockData;
232 936 : pPaintLockData = NULL; // nicht weitersammeln
233 :
234 936 : ScRangeListRef xRangeList = pPaint->GetRangeList();
235 936 : if (xRangeList)
236 : {
237 602 : sal_uInt16 nParts = pPaint->GetParts();
238 1337 : for ( size_t i = 0, nCount = xRangeList->size(); i < nCount; i++ )
239 : {
240 : //! nExtFlags ???
241 735 : ScRange aRange = *(*xRangeList)[i];
242 1470 : PostPaint( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab(),
243 1470 : aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab(),
244 3675 : nParts );
245 : }
246 : }
247 :
248 936 : if ( pPaint->GetModified() )
249 348 : SetDocumentModified();
250 :
251 936 : delete pPaint;
252 : }
253 : }
254 : else
255 : {
256 : OSL_FAIL("UnlockPaint ohne LockPaint");
257 : }
258 965 : }
259 :
260 686 : void ScDocShell::LockDocument_Impl(sal_uInt16 nNew)
261 : {
262 686 : if (!nDocumentLock)
263 : {
264 684 : ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
265 684 : if (pDrawLayer)
266 106 : pDrawLayer->setLock(true);
267 : }
268 686 : nDocumentLock = nNew;
269 686 : }
270 :
271 680 : void ScDocShell::UnlockDocument_Impl(sal_uInt16 nNew)
272 : {
273 680 : nDocumentLock = nNew;
274 680 : if (!nDocumentLock)
275 : {
276 680 : ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
277 680 : if (pDrawLayer)
278 186 : pDrawLayer->setLock(false);
279 : }
280 680 : }
281 :
282 2 : void ScDocShell::SetLockCount(sal_uInt16 nNew)
283 : {
284 2 : if (nNew) // setzen
285 : {
286 1 : if ( !pPaintLockData )
287 0 : pPaintLockData = new ScPaintLockData;
288 1 : pPaintLockData->SetLevel(nNew-1, true);
289 1 : LockDocument_Impl(nNew);
290 : }
291 1 : else if (pPaintLockData) // loeschen
292 : {
293 1 : pPaintLockData->SetLevel(0, true); // bei Unlock sofort ausfuehren
294 1 : UnlockPaint_Impl(true); // jetzt
295 1 : UnlockDocument_Impl(0);
296 : }
297 2 : }
298 :
299 285 : void ScDocShell::LockPaint()
300 : {
301 285 : LockPaint_Impl(false);
302 285 : }
303 :
304 285 : void ScDocShell::UnlockPaint()
305 : {
306 285 : UnlockPaint_Impl(false);
307 285 : }
308 :
309 685 : void ScDocShell::LockDocument()
310 : {
311 685 : LockPaint_Impl(true);
312 685 : LockDocument_Impl(nDocumentLock + 1);
313 685 : }
314 :
315 679 : void ScDocShell::UnlockDocument()
316 : {
317 679 : if (nDocumentLock)
318 : {
319 679 : UnlockPaint_Impl(true);
320 679 : UnlockDocument_Impl(nDocumentLock - 1);
321 : }
322 : else
323 : {
324 : OSL_FAIL("UnlockDocument without LockDocument");
325 : }
326 679 : }
327 :
328 1 : void ScDocShell::SetInplace( bool bInplace )
329 : {
330 1 : if (bIsInplace != bInplace)
331 : {
332 1 : bIsInplace = bInplace;
333 1 : CalcOutputFactor();
334 : }
335 1 : }
336 :
337 2047 : void ScDocShell::CalcOutputFactor()
338 : {
339 2047 : if (bIsInplace)
340 : {
341 924 : nPrtToScreenFactor = 1.0; // passt sonst nicht zur inaktiven Darstellung
342 1860 : return;
343 : }
344 :
345 1123 : bool bTextWysiwyg = SC_MOD()->GetInputOptions().GetTextWysiwyg();
346 1123 : if (bTextWysiwyg)
347 : {
348 12 : nPrtToScreenFactor = 1.0;
349 12 : return;
350 : }
351 :
352 : OUString aTestString(
353 1111 : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789");
354 1111 : long nPrinterWidth = 0;
355 1111 : long nWindowWidth = 0;
356 1111 : const ScPatternAttr* pPattern = static_cast<const ScPatternAttr*>(&aDocument.GetPool()->
357 1111 : GetDefaultItem(ATTR_PATTERN));
358 :
359 2222 : vcl::Font aDefFont;
360 1111 : OutputDevice* pRefDev = GetRefDevice();
361 2222 : MapMode aOldMode = pRefDev->GetMapMode();
362 2222 : vcl::Font aOldFont = pRefDev->GetFont();
363 :
364 1111 : pRefDev->SetMapMode(MAP_PIXEL);
365 1111 : pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, pRefDev); // font color doesn't matter here
366 1111 : pRefDev->SetFont(aDefFont);
367 1111 : nPrinterWidth = pRefDev->PixelToLogic( Size( pRefDev->GetTextWidth(aTestString), 0 ), MAP_100TH_MM ).Width();
368 1111 : pRefDev->SetFont(aOldFont);
369 1111 : pRefDev->SetMapMode(aOldMode);
370 :
371 2222 : ScopedVclPtrInstance< VirtualDevice > pVirtWindow( *Application::GetDefaultDevice() );
372 1111 : pVirtWindow->SetMapMode(MAP_PIXEL);
373 1111 : pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, pVirtWindow); // font color doesn't matter here
374 1111 : pVirtWindow->SetFont(aDefFont);
375 1111 : nWindowWidth = pVirtWindow->GetTextWidth(aTestString);
376 1111 : nWindowWidth = (long) ( nWindowWidth / ScGlobal::nScreenPPTX * HMM_PER_TWIPS );
377 :
378 1111 : if (nPrinterWidth && nWindowWidth)
379 1111 : nPrtToScreenFactor = nPrinterWidth / (double) nWindowWidth;
380 : else
381 : {
382 : OSL_FAIL("GetTextSize gibt 0 ??");
383 0 : nPrtToScreenFactor = 1.0;
384 1111 : }
385 : }
386 :
387 609 : void ScDocShell::InitOptions(bool bForLoading) // called from InitNew and Load
388 : {
389 : // Einstellungen aus dem SpellCheckCfg kommen in Doc- und ViewOptions
390 :
391 : sal_uInt16 nDefLang, nCjkLang, nCtlLang;
392 : bool bAutoSpell;
393 609 : ScModule::GetSpellSettings( nDefLang, nCjkLang, nCtlLang, bAutoSpell );
394 609 : ScModule* pScMod = SC_MOD();
395 :
396 609 : ScDocOptions aDocOpt = pScMod->GetDocOptions();
397 1218 : ScFormulaOptions aFormulaOpt = pScMod->GetFormulaOptions();
398 1218 : ScViewOptions aViewOpt = pScMod->GetViewOptions();
399 609 : aDocOpt.SetAutoSpell( bAutoSpell );
400 :
401 : // zweistellige Jahreszahleneingabe aus Extras->Optionen->Allgemein->Sonstiges
402 609 : aDocOpt.SetYear2000( sal::static_int_cast<sal_uInt16>( ::utl::MiscCfg().GetYear2000() ) );
403 :
404 609 : if (bForLoading)
405 : {
406 : // #i112123# No style:decimal-places attribute means automatic decimals, not the configured default,
407 : // so it must not be taken from the global options.
408 : // Calculation settings are handled separately in ScXMLBodyContext::EndElement.
409 168 : aDocOpt.SetStdPrecision( SvNumberFormatter::UNLIMITED_PRECISION );
410 :
411 : // fdo#78294 The default null-date if
412 : // <table:null-date table:date-value='...' />
413 : // is absent is 1899-12-30 regardless what the configuration is set to.
414 : // Import filters may override this value.
415 168 : aDocOpt.SetDate( 30, 12, 1899);
416 : }
417 :
418 609 : aDocument.SetDocOptions( aDocOpt );
419 609 : aDocument.SetViewOptions( aViewOpt );
420 609 : SetFormulaOptions( aFormulaOpt, bForLoading );
421 :
422 : // Druck-Optionen werden jetzt direkt vor dem Drucken gesetzt
423 :
424 1218 : aDocument.SetLanguage( (LanguageType) nDefLang, (LanguageType) nCjkLang, (LanguageType) nCtlLang );
425 609 : }
426 :
427 0 : Printer* ScDocShell::GetDocumentPrinter() // fuer OLE
428 : {
429 0 : return aDocument.GetPrinter();
430 : }
431 :
432 1612 : SfxPrinter* ScDocShell::GetPrinter(bool bCreateIfNotExist)
433 : {
434 1612 : return aDocument.GetPrinter(bCreateIfNotExist);
435 : }
436 :
437 1250 : void ScDocShell::UpdateFontList()
438 : {
439 1250 : delete pImpl->pFontList;
440 : // pImpl->pFontList = new FontList( GetPrinter(), Application::GetDefaultDevice() );
441 1250 : pImpl->pFontList = new FontList( GetRefDevice(), NULL, false ); // sal_False or sal_True???
442 1250 : SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
443 1250 : PutItem( aFontListItem );
444 :
445 1250 : CalcOutputFactor();
446 1250 : }
447 :
448 2416 : OutputDevice* ScDocShell::GetRefDevice()
449 : {
450 2416 : return aDocument.GetRefDevice();
451 : }
452 :
453 108 : sal_uInt16 ScDocShell::SetPrinter( SfxPrinter* pNewPrinter, SfxPrinterChangeFlags nDiffFlags )
454 : {
455 108 : SfxPrinter *pOld = aDocument.GetPrinter( false );
456 108 : if ( pOld && pOld->IsPrinting() )
457 0 : return SFX_PRINTERROR_BUSY;
458 :
459 108 : if (nDiffFlags & SfxPrinterChangeFlags::PRINTER)
460 : {
461 108 : if ( aDocument.GetPrinter() != pNewPrinter )
462 : {
463 108 : aDocument.SetPrinter( pNewPrinter );
464 108 : aDocument.SetPrintOptions();
465 :
466 : // MT: Use UpdateFontList: Will use Printer fonts only if needed!
467 : /*
468 : delete pImpl->pFontList;
469 : pImpl->pFontList = new FontList( pNewPrinter, Application::GetDefaultDevice() );
470 : SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
471 : PutItem( aFontListItem );
472 :
473 : CalcOutputFactor();
474 : */
475 108 : if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
476 0 : UpdateFontList();
477 :
478 108 : ScModule* pScMod = SC_MOD();
479 108 : SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this );
480 216 : while (pFrame)
481 : {
482 0 : SfxViewShell* pSh = pFrame->GetViewShell();
483 0 : if (pSh && pSh->ISA(ScTabViewShell))
484 : {
485 0 : ScTabViewShell* pViewSh = static_cast<ScTabViewShell*>(pSh);
486 0 : ScInputHandler* pInputHdl = pScMod->GetInputHdl(pViewSh);
487 0 : if (pInputHdl)
488 0 : pInputHdl->UpdateRefDevice();
489 : }
490 0 : pFrame = SfxViewFrame::GetNext( *pFrame, this );
491 : }
492 : }
493 : }
494 0 : else if (nDiffFlags & SfxPrinterChangeFlags::JOBSETUP)
495 : {
496 0 : SfxPrinter* pOldPrinter = aDocument.GetPrinter();
497 0 : if (pOldPrinter)
498 : {
499 0 : pOldPrinter->SetJobSetup( pNewPrinter->GetJobSetup() );
500 :
501 : // #i6706# Call SetPrinter with the old printer again, so the drawing layer
502 : // RefDevice is set (calling ReformatAllTextObjects and rebuilding charts),
503 : // because the JobSetup (printer device settings) may affect text layout.
504 0 : aDocument.SetPrinter( pOldPrinter );
505 0 : CalcOutputFactor(); // also with the new settings
506 : }
507 : }
508 :
509 108 : if (nDiffFlags & SfxPrinterChangeFlags::OPTIONS)
510 : {
511 108 : aDocument.SetPrintOptions(); //! aus neuem Printer ???
512 : }
513 :
514 108 : if (nDiffFlags & (SfxPrinterChangeFlags::CHG_ORIENTATION | SfxPrinterChangeFlags::CHG_SIZE))
515 : {
516 108 : OUString aStyle = aDocument.GetPageStyle( GetCurTab() );
517 108 : ScStyleSheetPool* pStPl = aDocument.GetStyleSheetPool();
518 108 : SfxStyleSheet* pStyleSheet = static_cast<SfxStyleSheet*>(pStPl->Find(aStyle, SFX_STYLE_FAMILY_PAGE));
519 108 : if (pStyleSheet)
520 : {
521 108 : SfxItemSet& rSet = pStyleSheet->GetItemSet();
522 :
523 108 : if (nDiffFlags & SfxPrinterChangeFlags::CHG_ORIENTATION)
524 : {
525 108 : const SvxPageItem& rOldItem = static_cast<const SvxPageItem&>(rSet.Get(ATTR_PAGE));
526 108 : bool bWasLand = rOldItem.IsLandscape();
527 108 : bool bNewLand = ( pNewPrinter->GetOrientation() == ORIENTATION_LANDSCAPE );
528 108 : if (bNewLand != bWasLand)
529 : {
530 0 : SvxPageItem aNewItem( rOldItem );
531 0 : aNewItem.SetLandscape( bNewLand );
532 0 : rSet.Put( aNewItem );
533 :
534 : // Groesse umdrehen
535 0 : Size aOldSize = static_cast<const SvxSizeItem&>(rSet.Get(ATTR_PAGE_SIZE)).GetSize();
536 0 : Size aNewSize(aOldSize.Height(),aOldSize.Width());
537 0 : SvxSizeItem aNewSItem(ATTR_PAGE_SIZE,aNewSize);
538 0 : rSet.Put( aNewSItem );
539 : }
540 : }
541 108 : if (nDiffFlags & SfxPrinterChangeFlags::CHG_SIZE)
542 : {
543 108 : SvxSizeItem aPaperSizeItem( ATTR_PAGE_SIZE, SvxPaperInfo::GetPaperSize(pNewPrinter) );
544 108 : rSet.Put( aPaperSizeItem );
545 : }
546 108 : }
547 : }
548 :
549 108 : PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB,PAINT_ALL);
550 :
551 108 : return 0;
552 : }
553 :
554 0 : ScChangeAction* ScDocShell::GetChangeAction( const ScAddress& rPos )
555 : {
556 0 : ScChangeTrack* pTrack = GetDocument().GetChangeTrack();
557 0 : if (!pTrack)
558 0 : return NULL;
559 :
560 0 : SCTAB nTab = rPos.Tab();
561 :
562 0 : const ScChangeAction* pFound = NULL;
563 0 : long nModified = 0;
564 0 : const ScChangeAction* pAction = pTrack->GetFirst();
565 0 : while (pAction)
566 : {
567 0 : ScChangeActionType eType = pAction->GetType();
568 : //! ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc )...
569 0 : if ( pAction->IsVisible() && eType != SC_CAT_DELETE_TABS )
570 : {
571 0 : const ScBigRange& rBig = pAction->GetBigRange();
572 0 : if ( rBig.aStart.Tab() == nTab )
573 : {
574 0 : ScRange aRange = rBig.MakeRange();
575 :
576 0 : if ( eType == SC_CAT_DELETE_ROWS )
577 0 : aRange.aEnd.SetRow( aRange.aStart.Row() );
578 0 : else if ( eType == SC_CAT_DELETE_COLS )
579 0 : aRange.aEnd.SetCol( aRange.aStart.Col() );
580 :
581 0 : if ( aRange.In( rPos ) )
582 : {
583 0 : pFound = pAction; // der letzte gewinnt
584 0 : ++nModified;
585 : }
586 : }
587 0 : if ( pAction->GetType() == SC_CAT_MOVE )
588 : {
589 : ScRange aRange =
590 : static_cast<const ScChangeActionMove*>(pAction)->
591 0 : GetFromRange().MakeRange();
592 0 : if ( aRange.In( rPos ) )
593 : {
594 0 : pFound = pAction;
595 0 : ++nModified;
596 : }
597 : }
598 : }
599 0 : pAction = pAction->GetNext();
600 : }
601 :
602 0 : return const_cast<ScChangeAction*>(pFound);
603 : }
604 :
605 0 : void ScDocShell::SetChangeComment( ScChangeAction* pAction, const OUString& rComment )
606 : {
607 0 : if (pAction)
608 : {
609 0 : pAction->SetComment( rComment );
610 : //! Undo ???
611 0 : SetDocumentModified();
612 :
613 : // Dialog-Notify
614 0 : ScChangeTrack* pTrack = GetDocument().GetChangeTrack();
615 0 : if (pTrack)
616 : {
617 0 : sal_uLong nNumber = pAction->GetActionNumber();
618 0 : pTrack->NotifyModified( SC_CTM_CHANGE, nNumber, nNumber );
619 : }
620 : }
621 0 : }
622 :
623 0 : void ScDocShell::ExecuteChangeCommentDialog( ScChangeAction* pAction, vcl::Window* pParent, bool bPrevNext)
624 : {
625 0 : if (!pAction) return; // ohne Aktion ist nichts..
626 :
627 0 : OUString aComment = pAction->GetComment();
628 0 : OUString aAuthor = pAction->GetUser();
629 :
630 0 : DateTime aDT = pAction->GetDateTime();
631 0 : OUString aDate = ScGlobal::pLocaleData->getDate( aDT );
632 0 : aDate += " ";
633 0 : aDate += ScGlobal::pLocaleData->getTime( aDT, false, false );
634 :
635 0 : SfxItemSet aSet( GetPool(),
636 : SID_ATTR_POSTIT_AUTHOR, SID_ATTR_POSTIT_AUTHOR,
637 : SID_ATTR_POSTIT_DATE, SID_ATTR_POSTIT_DATE,
638 : SID_ATTR_POSTIT_TEXT, SID_ATTR_POSTIT_TEXT,
639 0 : 0 );
640 :
641 0 : aSet.Put( SvxPostItTextItem ( aComment, SID_ATTR_POSTIT_TEXT ) );
642 0 : aSet.Put( SvxPostItAuthorItem( aAuthor, SID_ATTR_POSTIT_AUTHOR ) );
643 0 : aSet.Put( SvxPostItDateItem ( aDate, SID_ATTR_POSTIT_DATE ) );
644 :
645 0 : boost::scoped_ptr<ScRedComDialog> pDlg(new ScRedComDialog( pParent, aSet,this,pAction,bPrevNext));
646 :
647 0 : pDlg->Execute();
648 : }
649 :
650 0 : void ScDocShell::CompareDocument( ScDocument& rOtherDoc )
651 : {
652 0 : ScChangeTrack* pTrack = aDocument.GetChangeTrack();
653 0 : if ( pTrack && pTrack->GetFirst() )
654 : {
655 : //! Changes vorhanden -> Nachfrage ob geloescht werden soll
656 : }
657 :
658 0 : aDocument.EndChangeTracking();
659 0 : aDocument.StartChangeTracking();
660 :
661 0 : OUString aOldUser;
662 0 : pTrack = aDocument.GetChangeTrack();
663 0 : if ( pTrack )
664 : {
665 0 : aOldUser = pTrack->GetUser();
666 :
667 : // check if comparing to same document
668 :
669 0 : OUString aThisFile;
670 0 : const SfxMedium* pThisMed = GetMedium();
671 0 : if (pThisMed)
672 0 : aThisFile = pThisMed->GetName();
673 0 : OUString aOtherFile;
674 0 : SfxObjectShell* pOtherSh = rOtherDoc.GetDocumentShell();
675 0 : if (pOtherSh)
676 : {
677 0 : const SfxMedium* pOtherMed = pOtherSh->GetMedium();
678 0 : if (pOtherMed)
679 0 : aOtherFile = pOtherMed->GetName();
680 : }
681 0 : bool bSameDoc = ( aThisFile == aOtherFile && !aThisFile.isEmpty() );
682 0 : if ( !bSameDoc )
683 : {
684 : // create change actions from comparing with the name of the user
685 : // who last saved the document
686 : // (only if comparing different documents)
687 :
688 : using namespace ::com::sun::star;
689 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
690 0 : GetModel(), uno::UNO_QUERY_THROW);
691 : uno::Reference<document::XDocumentProperties> xDocProps(
692 0 : xDPS->getDocumentProperties());
693 : OSL_ENSURE(xDocProps.is(), "no DocumentProperties");
694 0 : OUString aDocUser = xDocProps->getModifiedBy();
695 :
696 0 : if ( !aDocUser.isEmpty() )
697 0 : pTrack->SetUser( aDocUser );
698 0 : }
699 : }
700 :
701 0 : aDocument.CompareDocument( rOtherDoc );
702 :
703 0 : pTrack = aDocument.GetChangeTrack();
704 0 : if ( pTrack )
705 0 : pTrack->SetUser( aOldUser );
706 :
707 0 : PostPaintGridAll();
708 0 : SetDocumentModified();
709 0 : }
710 :
711 : // Merge (Aenderungen zusammenfuehren)
712 :
713 0 : static inline bool lcl_Equal( const ScChangeAction* pA, const ScChangeAction* pB, bool bIgnore100Sec )
714 : {
715 0 : return pA && pB &&
716 0 : pA->GetActionNumber() == pB->GetActionNumber() &&
717 0 : pA->GetType() == pB->GetType() &&
718 0 : pA->GetUser() == pB->GetUser() &&
719 : (bIgnore100Sec ?
720 0 : pA->GetDateTimeUTC().IsEqualIgnoreNanoSec( pB->GetDateTimeUTC() ) :
721 0 : pA->GetDateTimeUTC() == pB->GetDateTimeUTC());
722 : // State nicht vergleichen, falls eine alte Aenderung akzeptiert wurde
723 : }
724 :
725 0 : static bool lcl_FindAction( ScDocument* pDoc, const ScChangeAction* pAction, ScDocument* pSearchDoc, const ScChangeAction* pFirstSearchAction, const ScChangeAction* pLastSearchAction, bool bIgnore100Sec )
726 : {
727 0 : if ( !pDoc || !pAction || !pSearchDoc || !pFirstSearchAction || !pLastSearchAction )
728 : {
729 0 : return false;
730 : }
731 :
732 0 : sal_uLong nLastSearchAction = pLastSearchAction->GetActionNumber();
733 0 : const ScChangeAction* pA = pFirstSearchAction;
734 0 : while ( pA && pA->GetActionNumber() <= nLastSearchAction )
735 : {
736 0 : if ( pAction->GetType() == pA->GetType() &&
737 0 : pAction->GetUser() == pA->GetUser() &&
738 : (bIgnore100Sec ?
739 0 : pAction->GetDateTimeUTC().IsEqualIgnoreNanoSec( pA->GetDateTimeUTC() ) :
740 0 : pAction->GetDateTimeUTC() == pA->GetDateTimeUTC() ) &&
741 0 : pAction->GetBigRange() == pA->GetBigRange() )
742 : {
743 0 : OUString aActionDesc;
744 0 : pAction->GetDescription(aActionDesc, pDoc, true);
745 0 : OUString aADesc;
746 0 : pA->GetDescription(aADesc, pSearchDoc, true);
747 0 : if (aActionDesc.equals(aADesc))
748 : {
749 : OSL_FAIL( "lcl_FindAction(): found equal action!" );
750 0 : return true;
751 0 : }
752 : }
753 0 : pA = pA->GetNext();
754 : }
755 :
756 0 : return false;
757 : }
758 :
759 0 : void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheckDuplicates, sal_uLong nOffset, ScChangeActionMergeMap* pMergeMap, bool bInverseMap )
760 : {
761 0 : ScTabViewShell* pViewSh = GetBestViewShell( false ); //! Funktionen an die DocShell
762 0 : if (!pViewSh)
763 0 : return;
764 :
765 0 : ScChangeTrack* pSourceTrack = rOtherDoc.GetChangeTrack();
766 0 : if (!pSourceTrack)
767 0 : return; //! nichts zu tun - Fehlermeldung?
768 :
769 0 : ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
770 0 : if ( !pThisTrack )
771 : { // anschalten
772 0 : aDocument.StartChangeTracking();
773 0 : pThisTrack = aDocument.GetChangeTrack();
774 : OSL_ENSURE(pThisTrack,"ChangeTracking nicht angeschaltet?");
775 0 : if ( !bShared )
776 : {
777 : // visuelles RedLining einschalten
778 0 : ScChangeViewSettings aChangeViewSet;
779 0 : aChangeViewSet.SetShowChanges(true);
780 0 : aDocument.SetChangeViewSettings(aChangeViewSet);
781 : }
782 : }
783 :
784 : // include Nano seconds in compare?
785 0 : bool bIgnore100Sec = !pSourceTrack->IsTimeNanoSeconds() ||
786 0 : !pThisTrack->IsTimeNanoSeconds();
787 :
788 : // gemeinsame Ausgangsposition suchen
789 0 : sal_uLong nFirstNewNumber = 0;
790 0 : const ScChangeAction* pSourceAction = pSourceTrack->GetFirst();
791 0 : const ScChangeAction* pThisAction = pThisTrack->GetFirst();
792 : // skip identical actions
793 0 : while ( lcl_Equal( pSourceAction, pThisAction, bIgnore100Sec ) )
794 : {
795 0 : nFirstNewNumber = pSourceAction->GetActionNumber() + 1;
796 0 : pSourceAction = pSourceAction->GetNext();
797 0 : pThisAction = pThisAction->GetNext();
798 : }
799 : // pSourceAction und pThisAction zeigen jetzt auf die ersten "eigenen" Aktionen
800 : // Die gemeinsamen Aktionen davor interessieren ueberhaupt nicht
801 :
802 : //! Abfrage, ob die Dokumente vor dem Change-Tracking gleich waren !!!
803 :
804 0 : const ScChangeAction* pFirstMergeAction = pSourceAction;
805 0 : const ScChangeAction* pFirstSearchAction = pThisAction;
806 :
807 : // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
808 0 : const ScChangeAction* pLastSearchAction = pThisTrack->GetLast();
809 :
810 : // MergeChangeData aus den folgenden Aktionen erzeugen
811 0 : sal_uLong nNewActionCount = 0;
812 0 : const ScChangeAction* pCount = pSourceAction;
813 0 : while ( pCount )
814 : {
815 0 : if ( bShared || !ScChangeTrack::MergeIgnore( *pCount, nFirstNewNumber ) )
816 0 : ++nNewActionCount;
817 0 : pCount = pCount->GetNext();
818 : }
819 0 : if (!nNewActionCount)
820 0 : return; //! nichts zu tun - Fehlermeldung?
821 : // ab hier kein return mehr
822 :
823 : ScProgress aProgress( this, OUString("..."),
824 0 : nNewActionCount );
825 :
826 0 : sal_uLong nLastMergeAction = pSourceTrack->GetLast()->GetActionNumber();
827 : // UpdateReference-Undo, gueltige Referenzen fuer den letzten gemeinsamen Zustand
828 0 : pSourceTrack->MergePrepare( const_cast<ScChangeAction*>(pFirstMergeAction), bShared );
829 :
830 : // MergeChangeData an alle noch folgenden Aktionen in diesem Dokument anpassen
831 : // -> Referenzen gueltig fuer dieses Dokument
832 0 : while ( pThisAction )
833 : {
834 : // #i87049# [Collaboration] Conflict between delete row and insert content is not merged correctly
835 0 : if ( !bShared || !ScChangeTrack::MergeIgnore( *pThisAction, nFirstNewNumber ) )
836 : {
837 0 : ScChangeActionType eType = pThisAction->GetType();
838 0 : switch ( eType )
839 : {
840 : case SC_CAT_INSERT_COLS :
841 : case SC_CAT_INSERT_ROWS :
842 : case SC_CAT_INSERT_TABS :
843 0 : pSourceTrack->AppendInsert( pThisAction->GetBigRange().MakeRange() );
844 0 : break;
845 : case SC_CAT_DELETE_COLS :
846 : case SC_CAT_DELETE_ROWS :
847 : case SC_CAT_DELETE_TABS :
848 : {
849 0 : const ScChangeActionDel* pDel = static_cast<const ScChangeActionDel*>(pThisAction);
850 0 : if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
851 : { // deleted Table enthaelt deleted Cols, die nicht
852 : sal_uLong nStart, nEnd;
853 : pSourceTrack->AppendDeleteRange(
854 0 : pDel->GetOverAllRange().MakeRange(), NULL, nStart, nEnd );
855 : }
856 : }
857 0 : break;
858 : case SC_CAT_MOVE :
859 : {
860 0 : const ScChangeActionMove* pMove = static_cast<const ScChangeActionMove*>(pThisAction);
861 0 : pSourceTrack->AppendMove( pMove->GetFromRange().MakeRange(),
862 0 : pMove->GetBigRange().MakeRange(), NULL );
863 : }
864 0 : break;
865 : default:
866 : {
867 : // added to avoid warnings
868 : }
869 : }
870 : }
871 0 : pThisAction = pThisAction->GetNext();
872 : }
873 :
874 0 : LockPaint(); // #i73877# no repainting after each action
875 :
876 : // MergeChangeData in das aktuelle Dokument uebernehmen
877 0 : bool bHasRejected = false;
878 0 : OUString aOldUser = pThisTrack->GetUser();
879 0 : pThisTrack->SetUseFixDateTime( true );
880 0 : ScMarkData& rMarkData = pViewSh->GetViewData().GetMarkData();
881 0 : ScMarkData aOldMarkData( rMarkData );
882 0 : pSourceAction = pFirstMergeAction;
883 0 : while ( pSourceAction && pSourceAction->GetActionNumber() <= nLastMergeAction )
884 : {
885 0 : bool bMergeAction = false;
886 0 : if ( bShared )
887 : {
888 0 : if ( !bCheckDuplicates || !lcl_FindAction( &rOtherDoc, pSourceAction, &aDocument, pFirstSearchAction, pLastSearchAction, bIgnore100Sec ) )
889 : {
890 0 : bMergeAction = true;
891 : }
892 : }
893 : else
894 : {
895 0 : if ( !ScChangeTrack::MergeIgnore( *pSourceAction, nFirstNewNumber ) )
896 : {
897 0 : bMergeAction = true;
898 : }
899 : }
900 :
901 0 : if ( bMergeAction )
902 : {
903 0 : ScChangeActionType eSourceType = pSourceAction->GetType();
904 0 : if ( !bShared && pSourceAction->IsDeletedIn() )
905 : {
906 : //! muss hier noch festgestellt werden, ob wirklich in
907 : //! _diesem_ Dokument geloescht?
908 :
909 : // liegt in einem Bereich, der in diesem Dokument geloescht wurde
910 : // -> wird weggelassen
911 : //! ??? Loesch-Aktion rueckgaengig machen ???
912 : //! ??? Aktion irgendwo anders speichern ???
913 : #if OSL_DEBUG_LEVEL > 0
914 : OUString aValue;
915 : if ( eSourceType == SC_CAT_CONTENT )
916 : static_cast<const ScChangeActionContent*>(pSourceAction)->GetNewString( aValue, &aDocument );
917 : OStringBuffer aError(OUStringToOString(aValue,
918 : osl_getThreadTextEncoding()));
919 : aError.append(" weggelassen");
920 : OSL_FAIL( aError.getStr() );
921 : #endif
922 : }
923 : else
924 : {
925 : //! Datum/Autor/Kommentar der Source-Aktion uebernehmen!
926 :
927 0 : pThisTrack->SetUser( pSourceAction->GetUser() );
928 0 : pThisTrack->SetFixDateTimeUTC( pSourceAction->GetDateTimeUTC() );
929 0 : sal_uLong nOldActionMax = pThisTrack->GetActionMax();
930 :
931 0 : bool bExecute = true;
932 0 : sal_uLong nReject = pSourceAction->GetRejectAction();
933 0 : if ( nReject )
934 : {
935 0 : if ( bShared )
936 : {
937 0 : if ( nReject >= nFirstNewNumber )
938 : {
939 0 : nReject += nOffset;
940 : }
941 0 : ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
942 0 : if ( pOldAction && pOldAction->IsVirgin() )
943 : {
944 0 : pThisTrack->Reject( pOldAction );
945 0 : bHasRejected = true;
946 0 : bExecute = false;
947 : }
948 : }
949 : else
950 : {
951 : // alte Aktion (aus den gemeinsamen) ablehnen
952 0 : ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
953 0 : if (pOldAction && pOldAction->GetState() == SC_CAS_VIRGIN)
954 : {
955 : //! was passiert bei Aktionen, die in diesem Dokument accepted worden sind???
956 : //! Fehlermeldung oder was???
957 : //! oder Reject-Aenderung normal ausfuehren
958 :
959 0 : pThisTrack->Reject(pOldAction);
960 0 : bHasRejected = true; // fuer Paint
961 : }
962 0 : bExecute = false;
963 : }
964 : }
965 :
966 0 : if ( bExecute )
967 : {
968 : // normal ausfuehren
969 0 : ScRange aSourceRange = pSourceAction->GetBigRange().MakeRange();
970 0 : rMarkData.SelectOneTable( aSourceRange.aStart.Tab() );
971 0 : switch ( eSourceType )
972 : {
973 : case SC_CAT_CONTENT:
974 : {
975 : //! Test, ob es ganz unten im Dokument war, dann automatisches
976 : //! Zeilen-Einfuegen ???
977 :
978 : OSL_ENSURE( aSourceRange.aStart == aSourceRange.aEnd, "huch?" );
979 0 : ScAddress aPos = aSourceRange.aStart;
980 0 : OUString aValue;
981 0 : static_cast<const ScChangeActionContent*>(pSourceAction)->GetNewString( aValue, &aDocument );
982 0 : sal_uInt8 eMatrix = MM_NONE;
983 0 : const ScCellValue& rCell = static_cast<const ScChangeActionContent*>(pSourceAction)->GetNewCell();
984 0 : if (rCell.meType == CELLTYPE_FORMULA)
985 0 : eMatrix = rCell.mpFormula->GetMatrixFlag();
986 0 : switch ( eMatrix )
987 : {
988 : case MM_NONE :
989 0 : pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
990 0 : break;
991 : case MM_FORMULA :
992 : {
993 : SCCOL nCols;
994 : SCROW nRows;
995 0 : rCell.mpFormula->GetMatColsRows(nCols, nRows);
996 0 : aSourceRange.aEnd.SetCol( aPos.Col() + nCols - 1 );
997 0 : aSourceRange.aEnd.SetRow( aPos.Row() + nRows - 1 );
998 0 : aValue = aValue.copy(1, aValue.getLength()-2); // remove the 1st and last characters.
999 0 : GetDocFunc().EnterMatrix( aSourceRange,
1000 : NULL, NULL, aValue, false, false,
1001 0 : EMPTY_OUSTRING, formula::FormulaGrammar::GRAM_DEFAULT );
1002 : }
1003 0 : break;
1004 : case MM_REFERENCE : // do nothing
1005 0 : break;
1006 : case MM_FAKE :
1007 : OSL_FAIL( "MergeDocument: MatrixFlag MM_FAKE" );
1008 0 : pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
1009 0 : break;
1010 : default:
1011 : OSL_FAIL( "MergeDocument: unknown MatrixFlag" );
1012 0 : }
1013 : }
1014 0 : break;
1015 : case SC_CAT_INSERT_TABS :
1016 : {
1017 0 : OUString aName;
1018 0 : aDocument.CreateValidTabName( aName );
1019 0 : GetDocFunc().InsertTable( aSourceRange.aStart.Tab(), aName, true, false );
1020 : }
1021 0 : break;
1022 : case SC_CAT_INSERT_ROWS:
1023 0 : GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSROWS_BEFORE, true, false );
1024 0 : break;
1025 : case SC_CAT_INSERT_COLS:
1026 0 : GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSCOLS_BEFORE, true, false );
1027 0 : break;
1028 : case SC_CAT_DELETE_TABS :
1029 0 : GetDocFunc().DeleteTable( aSourceRange.aStart.Tab(), true, false );
1030 0 : break;
1031 : case SC_CAT_DELETE_ROWS:
1032 : {
1033 0 : const ScChangeActionDel* pDel = static_cast<const ScChangeActionDel*>(pSourceAction);
1034 0 : if ( pDel->IsTopDelete() )
1035 : {
1036 0 : aSourceRange = pDel->GetOverAllRange().MakeRange();
1037 0 : GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELROWS, true, false );
1038 :
1039 : // #i101099# [Collaboration] Changes are not correctly shown
1040 0 : if ( bShared )
1041 : {
1042 0 : ScChangeAction* pAct = pThisTrack->GetLast();
1043 0 : if ( pAct && pAct->GetType() == eSourceType && pAct->IsDeletedIn() && !pSourceAction->IsDeletedIn() )
1044 : {
1045 0 : pAct->RemoveAllDeletedIn();
1046 : }
1047 : }
1048 : }
1049 : }
1050 0 : break;
1051 : case SC_CAT_DELETE_COLS:
1052 : {
1053 0 : const ScChangeActionDel* pDel = static_cast<const ScChangeActionDel*>(pSourceAction);
1054 0 : if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
1055 : { // deleted Table enthaelt deleted Cols, die nicht
1056 0 : aSourceRange = pDel->GetOverAllRange().MakeRange();
1057 0 : GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELCOLS, true, false );
1058 : }
1059 : }
1060 0 : break;
1061 : case SC_CAT_MOVE :
1062 : {
1063 0 : const ScChangeActionMove* pMove = static_cast<const ScChangeActionMove*>(pSourceAction);
1064 0 : ScRange aFromRange( pMove->GetFromRange().MakeRange() );
1065 0 : GetDocFunc().MoveBlock( aFromRange,
1066 0 : aSourceRange.aStart, true, true, false, false );
1067 : }
1068 0 : break;
1069 : default:
1070 : {
1071 : // added to avoid warnings
1072 : }
1073 : }
1074 : }
1075 0 : const OUString& rComment = pSourceAction->GetComment();
1076 0 : if ( !rComment.isEmpty() )
1077 : {
1078 0 : ScChangeAction* pAct = pThisTrack->GetLast();
1079 0 : if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1080 0 : pAct->SetComment( rComment );
1081 : else
1082 : OSL_FAIL( "MergeDocument: wohin mit dem Kommentar?!?" );
1083 : }
1084 :
1085 : // Referenzen anpassen
1086 0 : pSourceTrack->MergeOwn( const_cast<ScChangeAction*>(pSourceAction), nFirstNewNumber, bShared );
1087 :
1088 : // merge action state
1089 0 : if ( bShared && !pSourceAction->IsRejected() )
1090 : {
1091 0 : ScChangeAction* pAct = pThisTrack->GetLast();
1092 0 : if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1093 : {
1094 0 : ScChangeTrack::MergeActionState( pAct, pSourceAction );
1095 : }
1096 : }
1097 :
1098 : // fill merge map
1099 0 : if ( bShared && pMergeMap )
1100 : {
1101 0 : ScChangeAction* pAct = pThisTrack->GetLast();
1102 0 : if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1103 : {
1104 0 : sal_uLong nActionMax = pAct->GetActionNumber();
1105 0 : sal_uLong nActionCount = nActionMax - nOldActionMax;
1106 0 : sal_uLong nAction = nActionMax - nActionCount + 1;
1107 0 : sal_uLong nSourceAction = pSourceAction->GetActionNumber() - nActionCount + 1;
1108 0 : while ( nAction <= nActionMax )
1109 : {
1110 0 : if ( bInverseMap )
1111 : {
1112 0 : (*pMergeMap)[ nAction++ ] = nSourceAction++;
1113 : }
1114 : else
1115 : {
1116 0 : (*pMergeMap)[ nSourceAction++ ] = nAction++;
1117 : }
1118 : }
1119 : }
1120 : }
1121 : }
1122 0 : aProgress.SetStateCountDown( --nNewActionCount );
1123 : }
1124 0 : pSourceAction = pSourceAction->GetNext();
1125 : }
1126 :
1127 0 : rMarkData = aOldMarkData;
1128 0 : pThisTrack->SetUser(aOldUser);
1129 0 : pThisTrack->SetUseFixDateTime( false );
1130 :
1131 0 : pSourceTrack->Clear(); //! der ist jetzt verhunzt
1132 :
1133 0 : if (bHasRejected)
1134 0 : PostPaintGridAll(); // Reject() paintet nicht selber
1135 :
1136 0 : UnlockPaint();
1137 : }
1138 :
1139 0 : bool ScDocShell::MergeSharedDocument( ScDocShell* pSharedDocShell )
1140 : {
1141 0 : if ( !pSharedDocShell )
1142 : {
1143 0 : return false;
1144 : }
1145 :
1146 0 : ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
1147 0 : if ( !pThisTrack )
1148 : {
1149 0 : return false;
1150 : }
1151 :
1152 0 : ScDocument& rSharedDoc = pSharedDocShell->GetDocument();
1153 0 : ScChangeTrack* pSharedTrack = rSharedDoc.GetChangeTrack();
1154 0 : if ( !pSharedTrack )
1155 : {
1156 0 : return false;
1157 : }
1158 :
1159 : // reset show changes
1160 0 : ScChangeViewSettings aChangeViewSet;
1161 0 : aChangeViewSet.SetShowChanges( false );
1162 0 : aDocument.SetChangeViewSettings( aChangeViewSet );
1163 :
1164 : // find first merge action in this document
1165 0 : bool bIgnore100Sec = !pThisTrack->IsTimeNanoSeconds() || !pSharedTrack->IsTimeNanoSeconds();
1166 0 : ScChangeAction* pThisAction = pThisTrack->GetFirst();
1167 0 : ScChangeAction* pSharedAction = pSharedTrack->GetFirst();
1168 0 : while ( lcl_Equal( pThisAction, pSharedAction, bIgnore100Sec ) )
1169 : {
1170 0 : pThisAction = pThisAction->GetNext();
1171 0 : pSharedAction = pSharedAction->GetNext();
1172 : }
1173 :
1174 0 : if ( pSharedAction )
1175 : {
1176 0 : if ( pThisAction )
1177 : {
1178 : // merge own changes into shared document
1179 0 : sal_uLong nActStartShared = pSharedAction->GetActionNumber();
1180 0 : sal_uLong nActEndShared = pSharedTrack->GetActionMax();
1181 0 : ScDocument* pTmpDoc = new ScDocument;
1182 0 : for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex )
1183 : {
1184 0 : OUString sTabName;
1185 0 : pTmpDoc->CreateValidTabName( sTabName );
1186 0 : pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
1187 0 : }
1188 0 : aDocument.GetChangeTrack()->Clone( pTmpDoc );
1189 0 : ScChangeActionMergeMap aOwnInverseMergeMap;
1190 0 : pSharedDocShell->MergeDocument( *pTmpDoc, true, true, 0, &aOwnInverseMergeMap, true );
1191 0 : delete pTmpDoc;
1192 0 : sal_uLong nActStartOwn = nActEndShared + 1;
1193 0 : sal_uLong nActEndOwn = pSharedTrack->GetActionMax();
1194 :
1195 : // find conflicts
1196 0 : ScConflictsList aConflictsList;
1197 0 : ScConflictsFinder aFinder( pSharedTrack, nActStartShared, nActEndShared, nActStartOwn, nActEndOwn, aConflictsList );
1198 0 : if ( aFinder.Find() )
1199 : {
1200 0 : ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnInverseMergeMap );
1201 0 : bool bLoop = true;
1202 0 : while ( bLoop )
1203 : {
1204 0 : bLoop = false;
1205 0 : ScopedVclPtrInstance< ScConflictsDlg > aDlg( GetActiveDialogParent(), GetViewData(), &rSharedDoc, aConflictsList );
1206 0 : if ( aDlg->Execute() == RET_CANCEL )
1207 : {
1208 0 : ScopedVclPtrInstance<QueryBox> aBox( GetActiveDialogParent(), WinBits( WB_YES_NO | WB_DEF_YES ),
1209 0 : ScGlobal::GetRscString( STR_DOC_WILLNOTBESAVED ) );
1210 0 : if ( aBox->Execute() == RET_YES )
1211 : {
1212 0 : return false;
1213 : }
1214 : else
1215 : {
1216 0 : bLoop = true;
1217 0 : }
1218 : }
1219 0 : }
1220 : }
1221 :
1222 : // undo own changes in shared document
1223 0 : pSharedTrack->Undo( nActStartOwn, nActEndOwn );
1224 :
1225 : // clone change track for merging into own document
1226 0 : pTmpDoc = new ScDocument;
1227 0 : for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex )
1228 : {
1229 0 : OUString sTabName;
1230 0 : pTmpDoc->CreateValidTabName( sTabName );
1231 0 : pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
1232 0 : }
1233 0 : pThisTrack->Clone( pTmpDoc );
1234 :
1235 : // undo own changes since last save in own document
1236 0 : sal_uLong nStartShared = pThisAction->GetActionNumber();
1237 0 : ScChangeAction* pAction = pThisTrack->GetLast();
1238 0 : while ( pAction && pAction->GetActionNumber() >= nStartShared )
1239 : {
1240 0 : pThisTrack->Reject( pAction, true );
1241 0 : pAction = pAction->GetPrev();
1242 : }
1243 :
1244 : // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
1245 0 : pThisTrack->Undo( nStartShared, pThisTrack->GetActionMax(), true );
1246 :
1247 : // merge shared changes into own document
1248 0 : ScChangeActionMergeMap aSharedMergeMap;
1249 0 : MergeDocument( rSharedDoc, true, true, 0, &aSharedMergeMap );
1250 0 : sal_uLong nEndShared = pThisTrack->GetActionMax();
1251 :
1252 : // resolve conflicts for shared non-content actions
1253 0 : if ( !aConflictsList.empty() )
1254 : {
1255 0 : ScConflictsListHelper::TransformConflictsList( aConflictsList, &aSharedMergeMap, NULL );
1256 0 : ScConflictsResolver aResolver( pThisTrack, aConflictsList );
1257 0 : pAction = pThisTrack->GetAction( nEndShared );
1258 0 : while ( pAction && pAction->GetActionNumber() >= nStartShared )
1259 : {
1260 : aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
1261 0 : false /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1262 0 : pAction = pAction->GetPrev();
1263 0 : }
1264 : }
1265 0 : nEndShared = pThisTrack->GetActionMax();
1266 :
1267 : // only show changes from shared document
1268 0 : aChangeViewSet.SetShowChanges( true );
1269 0 : aChangeViewSet.SetShowAccepted( true );
1270 0 : aChangeViewSet.SetHasActionRange( true );
1271 0 : aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
1272 0 : aDocument.SetChangeViewSettings( aChangeViewSet );
1273 :
1274 : // merge own changes back into own document
1275 0 : sal_uLong nStartOwn = nEndShared + 1;
1276 0 : ScChangeActionMergeMap aOwnMergeMap;
1277 0 : MergeDocument( *pTmpDoc, true, true, nEndShared - nStartShared + 1, &aOwnMergeMap );
1278 0 : delete pTmpDoc;
1279 0 : sal_uLong nEndOwn = pThisTrack->GetActionMax();
1280 :
1281 : // resolve conflicts for shared content actions and own actions
1282 0 : if ( !aConflictsList.empty() )
1283 : {
1284 0 : ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnMergeMap );
1285 0 : ScConflictsResolver aResolver( pThisTrack, aConflictsList );
1286 0 : pAction = pThisTrack->GetAction( nEndShared );
1287 0 : while ( pAction && pAction->GetActionNumber() >= nStartShared )
1288 : {
1289 : aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
1290 0 : true /*bHandleContentAction*/, false /*bHandleNonContentAction*/ );
1291 0 : pAction = pAction->GetPrev();
1292 : }
1293 :
1294 0 : pAction = pThisTrack->GetAction( nEndOwn );
1295 0 : while ( pAction && pAction->GetActionNumber() >= nStartOwn )
1296 : {
1297 : aResolver.HandleAction( pAction, false /*bIsSharedAction*/,
1298 0 : true /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1299 0 : pAction = pAction->GetPrev();
1300 0 : }
1301 : }
1302 0 : nEndOwn = pThisTrack->GetActionMax();
1303 : }
1304 : else
1305 : {
1306 : // merge shared changes into own document
1307 0 : sal_uLong nStartShared = pThisTrack->GetActionMax() + 1;
1308 0 : MergeDocument( rSharedDoc, true, true );
1309 0 : sal_uLong nEndShared = pThisTrack->GetActionMax();
1310 :
1311 : // only show changes from shared document
1312 0 : aChangeViewSet.SetShowChanges( true );
1313 0 : aChangeViewSet.SetShowAccepted( true );
1314 0 : aChangeViewSet.SetHasActionRange( true );
1315 0 : aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
1316 0 : aDocument.SetChangeViewSettings( aChangeViewSet );
1317 : }
1318 :
1319 : // update view
1320 0 : PostPaintExtras();
1321 0 : PostPaintGridAll();
1322 :
1323 0 : ScopedVclPtrInstance< InfoBox > aInfoBox( GetActiveDialogParent(), ScGlobal::GetRscString( STR_DOC_UPDATED ) );
1324 0 : aInfoBox->Execute();
1325 : }
1326 :
1327 0 : return ( pThisAction != NULL );
1328 156 : }
1329 :
1330 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|