1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
21 #include <com/sun/star/document/XDocumentProperties.hpp>
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>
39 #include "docshimp.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"
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"
58 #include "inputopt.hxx"
59 #include "drwlayer.hxx"
60 #include "inputhdl.hxx"
61 #include "conflictsdlg.hxx"
62 #include "globstr.hrc"
63 #include "markdata.hxx"
66 #include <comphelper/lok.hxx>
67 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
69 // Redraw - Benachrichtigungen
71 void ScDocShell::PostEditView( ScEditEngineDefaulter
* pEditEngine
, const ScAddress
& rCursorPos
)
73 // Broadcast( ScEditViewHint( pEditEngine, rCursorPos ) );
75 // Test: nur aktive ViewShell
77 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
78 if (pViewSh
&& pViewSh
->GetViewData().GetDocShell() == this)
80 ScEditViewHint
aHint( pEditEngine
, rCursorPos
);
81 pViewSh
->Notify( *this, aHint
);
85 void ScDocShell::PostDataChanged()
87 Broadcast( SfxSimpleHint( FID_DATACHANGED
) );
88 SfxGetpApp()->Broadcast(SfxSimpleHint( FID_ANYDATACHANGED
)); // Navigator
89 aDocument
.ClearFormulaContext();
90 //! Navigator direkt benachrichtigen!
93 void ScDocShell::PostPaint( SCCOL nStartCol
, SCROW nStartRow
, SCTAB nStartTab
,
94 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nEndTab
, sal_uInt16 nPart
,
95 sal_uInt16 nExtFlags
)
97 ScRange
aRange(nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
);
98 PostPaint(aRange
, nPart
, nExtFlags
);
101 void ScDocShell::PostPaint( const ScRangeList
& rRanges
, sal_uInt16 nPart
, sal_uInt16 nExtFlags
)
103 ScRangeList aPaintRanges
;
104 for (size_t i
= 0, n
= rRanges
.size(); i
< n
; ++i
)
106 const ScRange
& rRange
= *rRanges
[i
];
107 SCCOL nCol1
= rRange
.aStart
.Col(), nCol2
= rRange
.aEnd
.Col();
108 SCROW nRow1
= rRange
.aStart
.Row(), nRow2
= rRange
.aEnd
.Row();
109 SCTAB nTab1
= rRange
.aStart
.Tab(), nTab2
= rRange
.aEnd
.Tab();
111 if (!ValidCol(nCol1
)) nCol1
= MAXCOL
;
112 if (!ValidRow(nRow1
)) nRow1
= MAXROW
;
113 if (!ValidCol(nCol2
)) nCol2
= MAXCOL
;
114 if (!ValidRow(nRow2
)) nRow2
= MAXROW
;
116 if ( pPaintLockData
)
118 // #i54081# PAINT_EXTRAS still has to be broadcast because it changes the
119 // current sheet if it's invalid. All other flags added to pPaintLockData.
120 sal_uInt16 nLockPart
= nPart
& ~PAINT_EXTRAS
;
124 pPaintLockData
->AddRange( ScRange( nCol1
, nRow1
, nTab1
,
125 nCol2
, nRow2
, nTab2
), nLockPart
);
128 nPart
&= PAINT_EXTRAS
; // for broadcasting
133 if (nExtFlags
& SC_PF_LINES
) // Platz fuer Linien beruecksichtigen
135 //! Abfrage auf versteckte Spalten/Zeilen!
136 if (nCol1
>0) --nCol1
;
137 if (nCol2
<MAXCOL
) ++nCol2
;
138 if (nRow1
>0) --nRow1
;
139 if (nRow2
<MAXROW
) ++nRow2
;
142 // um zusammengefasste erweitern
143 if (nExtFlags
& SC_PF_TESTMERGE
)
144 aDocument
.ExtendMerge( nCol1
, nRow1
, nCol2
, nRow2
, nTab1
);
146 if ( nCol1
!= 0 || nCol2
!= MAXCOL
)
148 // Extend to whole rows if SC_PF_WHOLEROWS is set, or rotated or non-left
149 // aligned cells are contained (see UpdatePaintExt).
150 // Special handling for RTL text (#i9731#) is unnecessary now with full
151 // support of right-aligned text.
153 if ( ( nExtFlags
& SC_PF_WHOLEROWS
) ||
154 aDocument
.HasAttrib( nCol1
,nRow1
,nTab1
,
155 MAXCOL
,nRow2
,nTab2
, HASATTR_ROTATE
| HASATTR_RIGHTORCENTER
) )
161 aPaintRanges
.Append(ScRange(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
));
164 Broadcast(ScPaintHint(aPaintRanges
.Combine(), nPart
));
166 // LOK: we are supposed to update the row / columns headers (and actually
167 // the document size too - cell size affects that, obviously)
168 if ((nPart
& (PAINT_TOP
| PAINT_LEFT
)) && comphelper::LibreOfficeKit::isActive() && aDocument
.GetDrawLayer())
169 aDocument
.GetDrawLayer()->libreOfficeKitCallback(LOK_CALLBACK_DOCUMENT_SIZE_CHANGED
, "");
172 void ScDocShell::PostPaintGridAll()
174 PostPaint( 0,0,0, MAXCOL
,MAXROW
,MAXTAB
, PAINT_GRID
);
177 void ScDocShell::PostPaintCell( SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
179 PostPaint( nCol
,nRow
,nTab
, nCol
,nRow
,nTab
, PAINT_GRID
, SC_PF_TESTMERGE
);
182 void ScDocShell::PostPaintCell( const ScAddress
& rPos
)
184 PostPaintCell( rPos
.Col(), rPos
.Row(), rPos
.Tab() );
187 void ScDocShell::PostPaintExtras()
189 PostPaint( 0,0,0, MAXCOL
,MAXROW
,MAXTAB
, PAINT_EXTRAS
);
192 void ScDocShell::UpdatePaintExt( sal_uInt16
& rExtFlags
, const ScRange
& rRange
)
194 if ( ( rExtFlags
& SC_PF_LINES
) == 0 && aDocument
.HasAttrib( rRange
, HASATTR_PAINTEXT
) )
196 // If the range contains lines, shadow or conditional formats,
197 // set SC_PF_LINES to include one extra cell in all directions.
199 rExtFlags
|= SC_PF_LINES
;
202 if ( ( rExtFlags
& SC_PF_WHOLEROWS
) == 0 &&
203 ( rRange
.aStart
.Col() != 0 || rRange
.aEnd
.Col() != MAXCOL
) &&
204 aDocument
.HasAttrib( rRange
, HASATTR_ROTATE
| HASATTR_RIGHTORCENTER
) )
206 // If the range contains (logically) right- or center-aligned cells,
207 // or rotated cells, set SC_PF_WHOLEROWS to paint the whole rows.
208 // This test isn't needed after the cell changes, because it's also
209 // tested in PostPaint. UpdatePaintExt may later be changed to do this
210 // only if called before the changes.
212 rExtFlags
|= SC_PF_WHOLEROWS
;
216 void ScDocShell::UpdatePaintExt( sal_uInt16
& rExtFlags
, SCCOL nStartCol
, SCROW nStartRow
, SCTAB nStartTab
,
217 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nEndTab
)
219 UpdatePaintExt( rExtFlags
, ScRange( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
) );
222 void ScDocShell::LockPaint_Impl(bool bDoc
)
224 if ( !pPaintLockData
)
225 pPaintLockData
= new ScPaintLockData
;
226 pPaintLockData
->IncLevel(bDoc
);
229 void ScDocShell::UnlockPaint_Impl(bool bDoc
)
231 if ( pPaintLockData
)
233 if ( pPaintLockData
->GetLevel(bDoc
) )
234 pPaintLockData
->DecLevel(bDoc
);
235 if (!pPaintLockData
->GetLevel(!bDoc
) && !pPaintLockData
->GetLevel(bDoc
))
237 // Paint jetzt ausfuehren
239 ScPaintLockData
* pPaint
= pPaintLockData
;
240 pPaintLockData
= nullptr; // nicht weitersammeln
242 ScRangeListRef xRangeList
= pPaint
->GetRangeList();
245 sal_uInt16 nParts
= pPaint
->GetParts();
246 for ( size_t i
= 0, nCount
= xRangeList
->size(); i
< nCount
; i
++ )
249 ScRange aRange
= *(*xRangeList
)[i
];
250 PostPaint( aRange
.aStart
.Col(), aRange
.aStart
.Row(), aRange
.aStart
.Tab(),
251 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), aRange
.aEnd
.Tab(),
256 if ( pPaint
->GetModified() )
257 SetDocumentModified();
264 OSL_FAIL("UnlockPaint ohne LockPaint");
268 void ScDocShell::LockDocument_Impl(sal_uInt16 nNew
)
272 ScDrawLayer
* pDrawLayer
= aDocument
.GetDrawLayer();
274 pDrawLayer
->setLock(true);
276 nDocumentLock
= nNew
;
279 void ScDocShell::UnlockDocument_Impl(sal_uInt16 nNew
)
281 nDocumentLock
= nNew
;
284 ScDrawLayer
* pDrawLayer
= aDocument
.GetDrawLayer();
286 pDrawLayer
->setLock(false);
290 void ScDocShell::SetLockCount(sal_uInt16 nNew
)
294 if ( !pPaintLockData
)
295 pPaintLockData
= new ScPaintLockData
;
296 pPaintLockData
->SetDocLevel(nNew
-1);
297 LockDocument_Impl(nNew
);
299 else if (pPaintLockData
) // loeschen
301 pPaintLockData
->SetDocLevel(0); // bei Unlock sofort ausfuehren
302 UnlockPaint_Impl(true); // jetzt
303 UnlockDocument_Impl(0);
307 void ScDocShell::LockPaint()
309 LockPaint_Impl(false);
312 void ScDocShell::UnlockPaint()
314 UnlockPaint_Impl(false);
317 void ScDocShell::LockDocument()
319 LockPaint_Impl(true);
320 LockDocument_Impl(nDocumentLock
+ 1);
323 void ScDocShell::UnlockDocument()
327 UnlockPaint_Impl(true);
328 UnlockDocument_Impl(nDocumentLock
- 1);
332 OSL_FAIL("UnlockDocument without LockDocument");
336 void ScDocShell::SetInplace( bool bInplace
)
338 if (bIsInplace
!= bInplace
)
340 bIsInplace
= bInplace
;
345 void ScDocShell::CalcOutputFactor()
349 nPrtToScreenFactor
= 1.0; // passt sonst nicht zur inaktiven Darstellung
353 bool bTextWysiwyg
= SC_MOD()->GetInputOptions().GetTextWysiwyg();
356 nPrtToScreenFactor
= 1.0;
360 OUString
aTestString(
361 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789");
362 long nPrinterWidth
= 0;
363 long nWindowWidth
= 0;
364 const ScPatternAttr
* pPattern
= static_cast<const ScPatternAttr
*>(&aDocument
.GetPool()->
365 GetDefaultItem(ATTR_PATTERN
));
368 OutputDevice
* pRefDev
= GetRefDevice();
369 MapMode aOldMode
= pRefDev
->GetMapMode();
370 vcl::Font aOldFont
= pRefDev
->GetFont();
372 pRefDev
->SetMapMode(MAP_PIXEL
);
373 pPattern
->GetFont(aDefFont
, SC_AUTOCOL_BLACK
, pRefDev
); // font color doesn't matter here
374 pRefDev
->SetFont(aDefFont
);
375 nPrinterWidth
= pRefDev
->PixelToLogic( Size( pRefDev
->GetTextWidth(aTestString
), 0 ), MAP_100TH_MM
).Width();
376 pRefDev
->SetFont(aOldFont
);
377 pRefDev
->SetMapMode(aOldMode
);
379 ScopedVclPtrInstance
< VirtualDevice
> pVirtWindow( *Application::GetDefaultDevice() );
380 pVirtWindow
->SetMapMode(MAP_PIXEL
);
381 pPattern
->GetFont(aDefFont
, SC_AUTOCOL_BLACK
, pVirtWindow
); // font color doesn't matter here
382 pVirtWindow
->SetFont(aDefFont
);
383 nWindowWidth
= pVirtWindow
->GetTextWidth(aTestString
);
384 nWindowWidth
= (long) ( nWindowWidth
/ ScGlobal::nScreenPPTX
* HMM_PER_TWIPS
);
386 if (nPrinterWidth
&& nWindowWidth
)
387 nPrtToScreenFactor
= nPrinterWidth
/ (double) nWindowWidth
;
390 OSL_FAIL("GetTextSize gibt 0 ??");
391 nPrtToScreenFactor
= 1.0;
395 void ScDocShell::InitOptions(bool bForLoading
) // called from InitNew and Load
397 // Einstellungen aus dem SpellCheckCfg kommen in Doc- und ViewOptions
399 sal_uInt16 nDefLang
, nCjkLang
, nCtlLang
;
401 ScModule::GetSpellSettings( nDefLang
, nCjkLang
, nCtlLang
, bAutoSpell
);
402 ScModule
* pScMod
= SC_MOD();
404 ScDocOptions aDocOpt
= pScMod
->GetDocOptions();
405 ScFormulaOptions aFormulaOpt
= pScMod
->GetFormulaOptions();
406 ScViewOptions aViewOpt
= pScMod
->GetViewOptions();
407 aDocOpt
.SetAutoSpell( bAutoSpell
);
409 // zweistellige Jahreszahleneingabe aus Extras->Optionen->Allgemein->Sonstiges
410 aDocOpt
.SetYear2000( sal::static_int_cast
<sal_uInt16
>( ::utl::MiscCfg().GetYear2000() ) );
414 // #i112123# No style:decimal-places attribute means automatic decimals, not the configured default,
415 // so it must not be taken from the global options.
416 // Calculation settings are handled separately in ScXMLBodyContext::EndElement.
417 aDocOpt
.SetStdPrecision( SvNumberFormatter::UNLIMITED_PRECISION
);
419 // fdo#78294 The default null-date if
420 // <table:null-date table:date-value='...' />
421 // is absent is 1899-12-30 regardless what the configuration is set to.
422 // Import filters may override this value.
423 aDocOpt
.SetDate( 30, 12, 1899);
426 aDocument
.SetDocOptions( aDocOpt
);
427 aDocument
.SetViewOptions( aViewOpt
);
428 SetFormulaOptions( aFormulaOpt
, bForLoading
);
430 // Druck-Optionen werden jetzt direkt vor dem Drucken gesetzt
432 aDocument
.SetLanguage( (LanguageType
) nDefLang
, (LanguageType
) nCjkLang
, (LanguageType
) nCtlLang
);
435 Printer
* ScDocShell::GetDocumentPrinter() // fuer OLE
437 return aDocument
.GetPrinter();
440 SfxPrinter
* ScDocShell::GetPrinter(bool bCreateIfNotExist
)
442 return aDocument
.GetPrinter(bCreateIfNotExist
);
445 void ScDocShell::UpdateFontList()
447 delete pImpl
->pFontList
;
448 // pImpl->pFontList = new FontList( GetPrinter(), Application::GetDefaultDevice() );
449 pImpl
->pFontList
= new FontList( GetRefDevice(), nullptr, false ); // sal_False or sal_True???
450 SvxFontListItem
aFontListItem( pImpl
->pFontList
, SID_ATTR_CHAR_FONTLIST
);
451 PutItem( aFontListItem
);
456 OutputDevice
* ScDocShell::GetRefDevice()
458 return aDocument
.GetRefDevice();
461 sal_uInt16
ScDocShell::SetPrinter( SfxPrinter
* pNewPrinter
, SfxPrinterChangeFlags nDiffFlags
)
463 SfxPrinter
*pOld
= aDocument
.GetPrinter( false );
464 if ( pOld
&& pOld
->IsPrinting() )
465 return SFX_PRINTERROR_BUSY
;
467 if (nDiffFlags
& SfxPrinterChangeFlags::PRINTER
)
469 if ( aDocument
.GetPrinter() != pNewPrinter
)
471 aDocument
.SetPrinter( pNewPrinter
);
472 aDocument
.SetPrintOptions();
474 // MT: Use UpdateFontList: Will use Printer fonts only if needed!
476 delete pImpl->pFontList;
477 pImpl->pFontList = new FontList( pNewPrinter, Application::GetDefaultDevice() );
478 SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
479 PutItem( aFontListItem );
483 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
486 ScModule
* pScMod
= SC_MOD();
487 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst( this );
490 SfxViewShell
* pSh
= pFrame
->GetViewShell();
491 if (ScTabViewShell
* pViewSh
= dynamic_cast<ScTabViewShell
*>(pSh
))
493 ScInputHandler
* pInputHdl
= pScMod
->GetInputHdl(pViewSh
);
495 pInputHdl
->UpdateRefDevice();
497 pFrame
= SfxViewFrame::GetNext( *pFrame
, this );
501 else if (nDiffFlags
& SfxPrinterChangeFlags::JOBSETUP
)
503 SfxPrinter
* pOldPrinter
= aDocument
.GetPrinter();
506 pOldPrinter
->SetJobSetup( pNewPrinter
->GetJobSetup() );
508 // #i6706# Call SetPrinter with the old printer again, so the drawing layer
509 // RefDevice is set (calling ReformatAllTextObjects and rebuilding charts),
510 // because the JobSetup (printer device settings) may affect text layout.
511 aDocument
.SetPrinter( pOldPrinter
);
512 CalcOutputFactor(); // also with the new settings
516 if (nDiffFlags
& SfxPrinterChangeFlags::OPTIONS
)
518 aDocument
.SetPrintOptions(); //! aus neuem Printer ???
521 if (nDiffFlags
& (SfxPrinterChangeFlags::CHG_ORIENTATION
| SfxPrinterChangeFlags::CHG_SIZE
))
523 OUString aStyle
= aDocument
.GetPageStyle( GetCurTab() );
524 ScStyleSheetPool
* pStPl
= aDocument
.GetStyleSheetPool();
525 SfxStyleSheet
* pStyleSheet
= static_cast<SfxStyleSheet
*>(pStPl
->Find(aStyle
, SfxStyleFamily::Page
));
528 SfxItemSet
& rSet
= pStyleSheet
->GetItemSet();
530 if (nDiffFlags
& SfxPrinterChangeFlags::CHG_ORIENTATION
)
532 const SvxPageItem
& rOldItem
= static_cast<const SvxPageItem
&>(rSet
.Get(ATTR_PAGE
));
533 bool bWasLand
= rOldItem
.IsLandscape();
534 bool bNewLand
= ( pNewPrinter
->GetOrientation() == ORIENTATION_LANDSCAPE
);
535 if (bNewLand
!= bWasLand
)
537 SvxPageItem
aNewItem( rOldItem
);
538 aNewItem
.SetLandscape( bNewLand
);
539 rSet
.Put( aNewItem
);
542 Size aOldSize
= static_cast<const SvxSizeItem
&>(rSet
.Get(ATTR_PAGE_SIZE
)).GetSize();
543 Size
aNewSize(aOldSize
.Height(),aOldSize
.Width());
544 SvxSizeItem
aNewSItem(ATTR_PAGE_SIZE
,aNewSize
);
545 rSet
.Put( aNewSItem
);
548 if (nDiffFlags
& SfxPrinterChangeFlags::CHG_SIZE
)
550 SvxSizeItem
aPaperSizeItem( ATTR_PAGE_SIZE
, SvxPaperInfo::GetPaperSize(pNewPrinter
) );
551 rSet
.Put( aPaperSizeItem
);
556 PostPaint(0,0,0,MAXCOL
,MAXROW
,MAXTAB
,PAINT_ALL
);
561 ScChangeAction
* ScDocShell::GetChangeAction( const ScAddress
& rPos
)
563 ScChangeTrack
* pTrack
= GetDocument().GetChangeTrack();
567 SCTAB nTab
= rPos
.Tab();
569 const ScChangeAction
* pFound
= nullptr;
571 const ScChangeAction
* pAction
= pTrack
->GetFirst();
574 ScChangeActionType eType
= pAction
->GetType();
575 //! ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc )...
576 if ( pAction
->IsVisible() && eType
!= SC_CAT_DELETE_TABS
)
578 const ScBigRange
& rBig
= pAction
->GetBigRange();
579 if ( rBig
.aStart
.Tab() == nTab
)
581 ScRange aRange
= rBig
.MakeRange();
583 if ( eType
== SC_CAT_DELETE_ROWS
)
584 aRange
.aEnd
.SetRow( aRange
.aStart
.Row() );
585 else if ( eType
== SC_CAT_DELETE_COLS
)
586 aRange
.aEnd
.SetCol( aRange
.aStart
.Col() );
588 if ( aRange
.In( rPos
) )
590 pFound
= pAction
; // der letzte gewinnt
594 if ( pAction
->GetType() == SC_CAT_MOVE
)
597 static_cast<const ScChangeActionMove
*>(pAction
)->
598 GetFromRange().MakeRange();
599 if ( aRange
.In( rPos
) )
606 pAction
= pAction
->GetNext();
609 return const_cast<ScChangeAction
*>(pFound
);
612 void ScDocShell::SetChangeComment( ScChangeAction
* pAction
, const OUString
& rComment
)
616 pAction
->SetComment( rComment
);
618 SetDocumentModified();
621 ScChangeTrack
* pTrack
= GetDocument().GetChangeTrack();
624 sal_uLong nNumber
= pAction
->GetActionNumber();
625 pTrack
->NotifyModified( SC_CTM_CHANGE
, nNumber
, nNumber
);
630 void ScDocShell::ExecuteChangeCommentDialog( ScChangeAction
* pAction
, vcl::Window
* pParent
, bool bPrevNext
)
632 if (!pAction
) return; // ohne Aktion ist nichts..
634 OUString aComment
= pAction
->GetComment();
635 OUString aAuthor
= pAction
->GetUser();
637 DateTime aDT
= pAction
->GetDateTime();
638 OUString aDate
= ScGlobal::pLocaleData
->getDate( aDT
);
640 aDate
+= ScGlobal::pLocaleData
->getTime( aDT
, false );
642 SfxItemSet
aSet( GetPool(),
643 SID_ATTR_POSTIT_AUTHOR
, SID_ATTR_POSTIT_AUTHOR
,
644 SID_ATTR_POSTIT_DATE
, SID_ATTR_POSTIT_DATE
,
645 SID_ATTR_POSTIT_TEXT
, SID_ATTR_POSTIT_TEXT
,
648 aSet
.Put( SvxPostItTextItem ( aComment
, SID_ATTR_POSTIT_TEXT
) );
649 aSet
.Put( SvxPostItAuthorItem( aAuthor
, SID_ATTR_POSTIT_AUTHOR
) );
650 aSet
.Put( SvxPostItDateItem ( aDate
, SID_ATTR_POSTIT_DATE
) );
652 std::unique_ptr
<ScRedComDialog
> pDlg(new ScRedComDialog( pParent
, aSet
,this,pAction
,bPrevNext
));
657 void ScDocShell::CompareDocument( ScDocument
& rOtherDoc
)
659 ScChangeTrack
* pTrack
= aDocument
.GetChangeTrack();
660 if ( pTrack
&& pTrack
->GetFirst() )
662 //! Changes vorhanden -> Nachfrage ob geloescht werden soll
665 aDocument
.EndChangeTracking();
666 aDocument
.StartChangeTracking();
669 pTrack
= aDocument
.GetChangeTrack();
672 aOldUser
= pTrack
->GetUser();
674 // check if comparing to same document
677 const SfxMedium
* pThisMed
= GetMedium();
679 aThisFile
= pThisMed
->GetName();
681 SfxObjectShell
* pOtherSh
= rOtherDoc
.GetDocumentShell();
684 const SfxMedium
* pOtherMed
= pOtherSh
->GetMedium();
686 aOtherFile
= pOtherMed
->GetName();
688 bool bSameDoc
= ( aThisFile
== aOtherFile
&& !aThisFile
.isEmpty() );
691 // create change actions from comparing with the name of the user
692 // who last saved the document
693 // (only if comparing different documents)
695 using namespace ::com::sun::star
;
696 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
697 GetModel(), uno::UNO_QUERY_THROW
);
698 uno::Reference
<document::XDocumentProperties
> xDocProps(
699 xDPS
->getDocumentProperties());
700 OSL_ENSURE(xDocProps
.is(), "no DocumentProperties");
701 OUString aDocUser
= xDocProps
->getModifiedBy();
703 if ( !aDocUser
.isEmpty() )
704 pTrack
->SetUser( aDocUser
);
708 aDocument
.CompareDocument( rOtherDoc
);
710 pTrack
= aDocument
.GetChangeTrack();
712 pTrack
->SetUser( aOldUser
);
715 SetDocumentModified();
718 // Merge (Aenderungen zusammenfuehren)
720 static inline bool lcl_Equal( const ScChangeAction
* pA
, const ScChangeAction
* pB
, bool bIgnore100Sec
)
723 pA
->GetActionNumber() == pB
->GetActionNumber() &&
724 pA
->GetType() == pB
->GetType() &&
725 pA
->GetUser() == pB
->GetUser() &&
727 pA
->GetDateTimeUTC().IsEqualIgnoreNanoSec( pB
->GetDateTimeUTC() ) :
728 pA
->GetDateTimeUTC() == pB
->GetDateTimeUTC());
729 // State nicht vergleichen, falls eine alte Aenderung akzeptiert wurde
732 static bool lcl_FindAction( ScDocument
* pDoc
, const ScChangeAction
* pAction
, ScDocument
* pSearchDoc
, const ScChangeAction
* pFirstSearchAction
, const ScChangeAction
* pLastSearchAction
, bool bIgnore100Sec
)
734 if ( !pDoc
|| !pAction
|| !pSearchDoc
|| !pFirstSearchAction
|| !pLastSearchAction
)
739 sal_uLong nLastSearchAction
= pLastSearchAction
->GetActionNumber();
740 const ScChangeAction
* pA
= pFirstSearchAction
;
741 while ( pA
&& pA
->GetActionNumber() <= nLastSearchAction
)
743 if ( pAction
->GetType() == pA
->GetType() &&
744 pAction
->GetUser() == pA
->GetUser() &&
746 pAction
->GetDateTimeUTC().IsEqualIgnoreNanoSec( pA
->GetDateTimeUTC() ) :
747 pAction
->GetDateTimeUTC() == pA
->GetDateTimeUTC() ) &&
748 pAction
->GetBigRange() == pA
->GetBigRange() )
750 OUString aActionDesc
;
751 pAction
->GetDescription(aActionDesc
, pDoc
, true);
753 pA
->GetDescription(aADesc
, pSearchDoc
, true);
754 if (aActionDesc
.equals(aADesc
))
756 OSL_FAIL( "lcl_FindAction(): found equal action!" );
766 void ScDocShell::MergeDocument( ScDocument
& rOtherDoc
, bool bShared
, bool bCheckDuplicates
, sal_uLong nOffset
, ScChangeActionMergeMap
* pMergeMap
, bool bInverseMap
)
768 ScTabViewShell
* pViewSh
= GetBestViewShell( false ); //! Funktionen an die DocShell
772 ScChangeTrack
* pSourceTrack
= rOtherDoc
.GetChangeTrack();
774 return; //! nichts zu tun - Fehlermeldung?
776 ScChangeTrack
* pThisTrack
= aDocument
.GetChangeTrack();
779 aDocument
.StartChangeTracking();
780 pThisTrack
= aDocument
.GetChangeTrack();
781 OSL_ENSURE(pThisTrack
,"ChangeTracking nicht angeschaltet?");
784 // visuelles RedLining einschalten
785 ScChangeViewSettings aChangeViewSet
;
786 aChangeViewSet
.SetShowChanges(true);
787 aDocument
.SetChangeViewSettings(aChangeViewSet
);
791 // include Nano seconds in compare?
792 bool bIgnore100Sec
= !pSourceTrack
->IsTimeNanoSeconds() ||
793 !pThisTrack
->IsTimeNanoSeconds();
795 // gemeinsame Ausgangsposition suchen
796 sal_uLong nFirstNewNumber
= 0;
797 const ScChangeAction
* pSourceAction
= pSourceTrack
->GetFirst();
798 const ScChangeAction
* pThisAction
= pThisTrack
->GetFirst();
799 // skip identical actions
800 while ( lcl_Equal( pSourceAction
, pThisAction
, bIgnore100Sec
) )
802 nFirstNewNumber
= pSourceAction
->GetActionNumber() + 1;
803 pSourceAction
= pSourceAction
->GetNext();
804 pThisAction
= pThisAction
->GetNext();
806 // pSourceAction und pThisAction zeigen jetzt auf die ersten "eigenen" Aktionen
807 // Die gemeinsamen Aktionen davor interessieren ueberhaupt nicht
809 //! Abfrage, ob die Dokumente vor dem Change-Tracking gleich waren !!!
811 const ScChangeAction
* pFirstMergeAction
= pSourceAction
;
812 const ScChangeAction
* pFirstSearchAction
= pThisAction
;
814 // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
815 const ScChangeAction
* pLastSearchAction
= pThisTrack
->GetLast();
817 // MergeChangeData aus den folgenden Aktionen erzeugen
818 sal_uLong nNewActionCount
= 0;
819 const ScChangeAction
* pCount
= pSourceAction
;
822 if ( bShared
|| !ScChangeTrack::MergeIgnore( *pCount
, nFirstNewNumber
) )
824 pCount
= pCount
->GetNext();
826 if (!nNewActionCount
)
827 return; //! nichts zu tun - Fehlermeldung?
828 // ab hier kein return mehr
830 ScProgress
aProgress( this, OUString("..."),
831 nNewActionCount
, true );
833 sal_uLong nLastMergeAction
= pSourceTrack
->GetLast()->GetActionNumber();
834 // UpdateReference-Undo, gueltige Referenzen fuer den letzten gemeinsamen Zustand
835 pSourceTrack
->MergePrepare( const_cast<ScChangeAction
*>(pFirstMergeAction
), bShared
);
837 // MergeChangeData an alle noch folgenden Aktionen in diesem Dokument anpassen
838 // -> Referenzen gueltig fuer dieses Dokument
839 while ( pThisAction
)
841 // #i87049# [Collaboration] Conflict between delete row and insert content is not merged correctly
842 if ( !bShared
|| !ScChangeTrack::MergeIgnore( *pThisAction
, nFirstNewNumber
) )
844 ScChangeActionType eType
= pThisAction
->GetType();
847 case SC_CAT_INSERT_COLS
:
848 case SC_CAT_INSERT_ROWS
:
849 case SC_CAT_INSERT_TABS
:
850 pSourceTrack
->AppendInsert( pThisAction
->GetBigRange().MakeRange() );
852 case SC_CAT_DELETE_COLS
:
853 case SC_CAT_DELETE_ROWS
:
854 case SC_CAT_DELETE_TABS
:
856 const ScChangeActionDel
* pDel
= static_cast<const ScChangeActionDel
*>(pThisAction
);
857 if ( pDel
->IsTopDelete() && !pDel
->IsTabDeleteCol() )
858 { // deleted Table enthaelt deleted Cols, die nicht
859 sal_uLong nStart
, nEnd
;
860 pSourceTrack
->AppendDeleteRange(
861 pDel
->GetOverAllRange().MakeRange(), nullptr, nStart
, nEnd
);
867 const ScChangeActionMove
* pMove
= static_cast<const ScChangeActionMove
*>(pThisAction
);
868 pSourceTrack
->AppendMove( pMove
->GetFromRange().MakeRange(),
869 pMove
->GetBigRange().MakeRange(), nullptr );
874 // added to avoid warnings
878 pThisAction
= pThisAction
->GetNext();
881 LockPaint(); // #i73877# no repainting after each action
883 // MergeChangeData in das aktuelle Dokument uebernehmen
884 bool bHasRejected
= false;
885 OUString aOldUser
= pThisTrack
->GetUser();
886 pThisTrack
->SetUseFixDateTime( true );
887 ScMarkData
& rMarkData
= pViewSh
->GetViewData().GetMarkData();
888 ScMarkData
aOldMarkData( rMarkData
);
889 pSourceAction
= pFirstMergeAction
;
890 while ( pSourceAction
&& pSourceAction
->GetActionNumber() <= nLastMergeAction
)
892 bool bMergeAction
= false;
895 if ( !bCheckDuplicates
|| !lcl_FindAction( &rOtherDoc
, pSourceAction
, &aDocument
, pFirstSearchAction
, pLastSearchAction
, bIgnore100Sec
) )
902 if ( !ScChangeTrack::MergeIgnore( *pSourceAction
, nFirstNewNumber
) )
910 ScChangeActionType eSourceType
= pSourceAction
->GetType();
911 if ( !bShared
&& pSourceAction
->IsDeletedIn() )
913 //! muss hier noch festgestellt werden, ob wirklich in
914 //! _diesem_ Dokument geloescht?
916 // liegt in einem Bereich, der in diesem Dokument geloescht wurde
917 // -> wird weggelassen
918 //! ??? Loesch-Aktion rueckgaengig machen ???
919 //! ??? Aktion irgendwo anders speichern ???
920 #if OSL_DEBUG_LEVEL > 0
922 if ( eSourceType
== SC_CAT_CONTENT
)
923 static_cast<const ScChangeActionContent
*>(pSourceAction
)->GetNewString( aValue
, &aDocument
);
924 OStringBuffer
aError(OUStringToOString(aValue
,
925 osl_getThreadTextEncoding()));
926 aError
.append(" weggelassen");
927 OSL_FAIL( aError
.getStr() );
932 //! Datum/Autor/Kommentar der Source-Aktion uebernehmen!
934 pThisTrack
->SetUser( pSourceAction
->GetUser() );
935 pThisTrack
->SetFixDateTimeUTC( pSourceAction
->GetDateTimeUTC() );
936 sal_uLong nOldActionMax
= pThisTrack
->GetActionMax();
938 bool bExecute
= true;
939 sal_uLong nReject
= pSourceAction
->GetRejectAction();
944 if ( nReject
>= nFirstNewNumber
)
948 ScChangeAction
* pOldAction
= pThisTrack
->GetAction( nReject
);
949 if ( pOldAction
&& pOldAction
->IsVirgin() )
951 pThisTrack
->Reject( pOldAction
);
958 // alte Aktion (aus den gemeinsamen) ablehnen
959 ScChangeAction
* pOldAction
= pThisTrack
->GetAction( nReject
);
960 if (pOldAction
&& pOldAction
->GetState() == SC_CAS_VIRGIN
)
962 //! was passiert bei Aktionen, die in diesem Dokument accepted worden sind???
963 //! Fehlermeldung oder was???
964 //! oder Reject-Aenderung normal ausfuehren
966 pThisTrack
->Reject(pOldAction
);
967 bHasRejected
= true; // fuer Paint
976 ScRange aSourceRange
= pSourceAction
->GetBigRange().MakeRange();
977 rMarkData
.SelectOneTable( aSourceRange
.aStart
.Tab() );
978 switch ( eSourceType
)
982 //! Test, ob es ganz unten im Dokument war, dann automatisches
983 //! Zeilen-Einfuegen ???
985 OSL_ENSURE( aSourceRange
.aStart
== aSourceRange
.aEnd
, "huch?" );
986 ScAddress aPos
= aSourceRange
.aStart
;
988 static_cast<const ScChangeActionContent
*>(pSourceAction
)->GetNewString( aValue
, &aDocument
);
989 sal_uInt8 eMatrix
= MM_NONE
;
990 const ScCellValue
& rCell
= static_cast<const ScChangeActionContent
*>(pSourceAction
)->GetNewCell();
991 if (rCell
.meType
== CELLTYPE_FORMULA
)
992 eMatrix
= rCell
.mpFormula
->GetMatrixFlag();
996 pViewSh
->EnterData( aPos
.Col(), aPos
.Row(), aPos
.Tab(), aValue
);
1002 rCell
.mpFormula
->GetMatColsRows(nCols
, nRows
);
1003 aSourceRange
.aEnd
.SetCol( aPos
.Col() + nCols
- 1 );
1004 aSourceRange
.aEnd
.SetRow( aPos
.Row() + nRows
- 1 );
1005 aValue
= aValue
.copy(1, aValue
.getLength()-2); // remove the 1st and last characters.
1006 GetDocFunc().EnterMatrix( aSourceRange
,
1007 nullptr, nullptr, aValue
, false, false,
1008 EMPTY_OUSTRING
, formula::FormulaGrammar::GRAM_DEFAULT
);
1011 case MM_REFERENCE
: // do nothing
1016 case SC_CAT_INSERT_TABS
:
1019 aDocument
.CreateValidTabName( aName
);
1020 GetDocFunc().InsertTable( aSourceRange
.aStart
.Tab(), aName
, true, false );
1023 case SC_CAT_INSERT_ROWS
:
1024 GetDocFunc().InsertCells( aSourceRange
, nullptr, INS_INSROWS_BEFORE
, true, false );
1026 case SC_CAT_INSERT_COLS
:
1027 GetDocFunc().InsertCells( aSourceRange
, nullptr, INS_INSCOLS_BEFORE
, true, false );
1029 case SC_CAT_DELETE_TABS
:
1030 GetDocFunc().DeleteTable( aSourceRange
.aStart
.Tab(), true, false );
1032 case SC_CAT_DELETE_ROWS
:
1034 const ScChangeActionDel
* pDel
= static_cast<const ScChangeActionDel
*>(pSourceAction
);
1035 if ( pDel
->IsTopDelete() )
1037 aSourceRange
= pDel
->GetOverAllRange().MakeRange();
1038 GetDocFunc().DeleteCells( aSourceRange
, nullptr, DEL_DELROWS
, false );
1040 // #i101099# [Collaboration] Changes are not correctly shown
1043 ScChangeAction
* pAct
= pThisTrack
->GetLast();
1044 if ( pAct
&& pAct
->GetType() == eSourceType
&& pAct
->IsDeletedIn() && !pSourceAction
->IsDeletedIn() )
1046 pAct
->RemoveAllDeletedIn();
1052 case SC_CAT_DELETE_COLS
:
1054 const ScChangeActionDel
* pDel
= static_cast<const ScChangeActionDel
*>(pSourceAction
);
1055 if ( pDel
->IsTopDelete() && !pDel
->IsTabDeleteCol() )
1056 { // deleted Table enthaelt deleted Cols, die nicht
1057 aSourceRange
= pDel
->GetOverAllRange().MakeRange();
1058 GetDocFunc().DeleteCells( aSourceRange
, nullptr, DEL_DELCOLS
, false );
1064 const ScChangeActionMove
* pMove
= static_cast<const ScChangeActionMove
*>(pSourceAction
);
1065 ScRange
aFromRange( pMove
->GetFromRange().MakeRange() );
1066 GetDocFunc().MoveBlock( aFromRange
,
1067 aSourceRange
.aStart
, true, true, false, false );
1072 // added to avoid warnings
1076 const OUString
& rComment
= pSourceAction
->GetComment();
1077 if ( !rComment
.isEmpty() )
1079 ScChangeAction
* pAct
= pThisTrack
->GetLast();
1080 if ( pAct
&& pAct
->GetActionNumber() > nOldActionMax
)
1081 pAct
->SetComment( rComment
);
1083 OSL_FAIL( "MergeDocument: wohin mit dem Kommentar?!?" );
1086 // Referenzen anpassen
1087 pSourceTrack
->MergeOwn( const_cast<ScChangeAction
*>(pSourceAction
), nFirstNewNumber
, bShared
);
1089 // merge action state
1090 if ( bShared
&& !pSourceAction
->IsRejected() )
1092 ScChangeAction
* pAct
= pThisTrack
->GetLast();
1093 if ( pAct
&& pAct
->GetActionNumber() > nOldActionMax
)
1095 ScChangeTrack::MergeActionState( pAct
, pSourceAction
);
1100 if ( bShared
&& pMergeMap
)
1102 ScChangeAction
* pAct
= pThisTrack
->GetLast();
1103 if ( pAct
&& pAct
->GetActionNumber() > nOldActionMax
)
1105 sal_uLong nActionMax
= pAct
->GetActionNumber();
1106 sal_uLong nActionCount
= nActionMax
- nOldActionMax
;
1107 sal_uLong nAction
= nActionMax
- nActionCount
+ 1;
1108 sal_uLong nSourceAction
= pSourceAction
->GetActionNumber() - nActionCount
+ 1;
1109 while ( nAction
<= nActionMax
)
1113 (*pMergeMap
)[ nAction
++ ] = nSourceAction
++;
1117 (*pMergeMap
)[ nSourceAction
++ ] = nAction
++;
1123 aProgress
.SetStateCountDown( --nNewActionCount
);
1125 pSourceAction
= pSourceAction
->GetNext();
1128 rMarkData
= aOldMarkData
;
1129 pThisTrack
->SetUser(aOldUser
);
1130 pThisTrack
->SetUseFixDateTime( false );
1132 pSourceTrack
->Clear(); //! der ist jetzt verhunzt
1135 PostPaintGridAll(); // Reject() paintet nicht selber
1140 bool ScDocShell::MergeSharedDocument( ScDocShell
* pSharedDocShell
)
1142 if ( !pSharedDocShell
)
1147 ScChangeTrack
* pThisTrack
= aDocument
.GetChangeTrack();
1153 ScDocument
& rSharedDoc
= pSharedDocShell
->GetDocument();
1154 ScChangeTrack
* pSharedTrack
= rSharedDoc
.GetChangeTrack();
1155 if ( !pSharedTrack
)
1160 // reset show changes
1161 ScChangeViewSettings aChangeViewSet
;
1162 aChangeViewSet
.SetShowChanges( false );
1163 aDocument
.SetChangeViewSettings( aChangeViewSet
);
1165 // find first merge action in this document
1166 bool bIgnore100Sec
= !pThisTrack
->IsTimeNanoSeconds() || !pSharedTrack
->IsTimeNanoSeconds();
1167 ScChangeAction
* pThisAction
= pThisTrack
->GetFirst();
1168 ScChangeAction
* pSharedAction
= pSharedTrack
->GetFirst();
1169 while ( lcl_Equal( pThisAction
, pSharedAction
, bIgnore100Sec
) )
1171 pThisAction
= pThisAction
->GetNext();
1172 pSharedAction
= pSharedAction
->GetNext();
1175 if ( pSharedAction
)
1179 // merge own changes into shared document
1180 sal_uLong nActStartShared
= pSharedAction
->GetActionNumber();
1181 sal_uLong nActEndShared
= pSharedTrack
->GetActionMax();
1182 ScDocument
* pTmpDoc
= new ScDocument
;
1183 for ( sal_Int32 nIndex
= 0; nIndex
< aDocument
.GetTableCount(); ++nIndex
)
1186 pTmpDoc
->CreateValidTabName( sTabName
);
1187 pTmpDoc
->InsertTab( SC_TAB_APPEND
, sTabName
);
1189 aDocument
.GetChangeTrack()->Clone( pTmpDoc
);
1190 ScChangeActionMergeMap aOwnInverseMergeMap
;
1191 pSharedDocShell
->MergeDocument( *pTmpDoc
, true, true, 0, &aOwnInverseMergeMap
, true );
1193 sal_uLong nActStartOwn
= nActEndShared
+ 1;
1194 sal_uLong nActEndOwn
= pSharedTrack
->GetActionMax();
1197 ScConflictsList aConflictsList
;
1198 ScConflictsFinder
aFinder( pSharedTrack
, nActStartShared
, nActEndShared
, nActStartOwn
, nActEndOwn
, aConflictsList
);
1199 if ( aFinder
.Find() )
1201 ScConflictsListHelper::TransformConflictsList( aConflictsList
, nullptr, &aOwnInverseMergeMap
);
1206 ScopedVclPtrInstance
< ScConflictsDlg
> aDlg( GetActiveDialogParent(), GetViewData(), &rSharedDoc
, aConflictsList
);
1207 if ( aDlg
->Execute() == RET_CANCEL
)
1209 ScopedVclPtrInstance
<QueryBox
> aBox( GetActiveDialogParent(), WinBits( WB_YES_NO
| WB_DEF_YES
),
1210 ScGlobal::GetRscString( STR_DOC_WILLNOTBESAVED
) );
1211 if ( aBox
->Execute() == RET_YES
)
1223 // undo own changes in shared document
1224 pSharedTrack
->Undo( nActStartOwn
, nActEndOwn
);
1226 // clone change track for merging into own document
1227 pTmpDoc
= new ScDocument
;
1228 for ( sal_Int32 nIndex
= 0; nIndex
< aDocument
.GetTableCount(); ++nIndex
)
1231 pTmpDoc
->CreateValidTabName( sTabName
);
1232 pTmpDoc
->InsertTab( SC_TAB_APPEND
, sTabName
);
1234 pThisTrack
->Clone( pTmpDoc
);
1236 // undo own changes since last save in own document
1237 sal_uLong nStartShared
= pThisAction
->GetActionNumber();
1238 ScChangeAction
* pAction
= pThisTrack
->GetLast();
1239 while ( pAction
&& pAction
->GetActionNumber() >= nStartShared
)
1241 pThisTrack
->Reject( pAction
, true );
1242 pAction
= pAction
->GetPrev();
1245 // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
1246 pThisTrack
->Undo( nStartShared
, pThisTrack
->GetActionMax(), true );
1248 // merge shared changes into own document
1249 ScChangeActionMergeMap aSharedMergeMap
;
1250 MergeDocument( rSharedDoc
, true, true, 0, &aSharedMergeMap
);
1251 sal_uLong nEndShared
= pThisTrack
->GetActionMax();
1253 // resolve conflicts for shared non-content actions
1254 if ( !aConflictsList
.empty() )
1256 ScConflictsListHelper::TransformConflictsList( aConflictsList
, &aSharedMergeMap
, nullptr );
1257 ScConflictsResolver
aResolver( pThisTrack
, aConflictsList
);
1258 pAction
= pThisTrack
->GetAction( nEndShared
);
1259 while ( pAction
&& pAction
->GetActionNumber() >= nStartShared
)
1261 aResolver
.HandleAction( pAction
, true /*bIsSharedAction*/,
1262 false /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1263 pAction
= pAction
->GetPrev();
1266 nEndShared
= pThisTrack
->GetActionMax();
1268 // only show changes from shared document
1269 aChangeViewSet
.SetShowChanges( true );
1270 aChangeViewSet
.SetShowAccepted( true );
1271 aChangeViewSet
.SetHasActionRange();
1272 aChangeViewSet
.SetTheActionRange( nStartShared
, nEndShared
);
1273 aDocument
.SetChangeViewSettings( aChangeViewSet
);
1275 // merge own changes back into own document
1276 sal_uLong nStartOwn
= nEndShared
+ 1;
1277 ScChangeActionMergeMap aOwnMergeMap
;
1278 MergeDocument( *pTmpDoc
, true, true, nEndShared
- nStartShared
+ 1, &aOwnMergeMap
);
1280 sal_uLong nEndOwn
= pThisTrack
->GetActionMax();
1282 // resolve conflicts for shared content actions and own actions
1283 if ( !aConflictsList
.empty() )
1285 ScConflictsListHelper::TransformConflictsList( aConflictsList
, nullptr, &aOwnMergeMap
);
1286 ScConflictsResolver
aResolver( pThisTrack
, aConflictsList
);
1287 pAction
= pThisTrack
->GetAction( nEndShared
);
1288 while ( pAction
&& pAction
->GetActionNumber() >= nStartShared
)
1290 aResolver
.HandleAction( pAction
, true /*bIsSharedAction*/,
1291 true /*bHandleContentAction*/, false /*bHandleNonContentAction*/ );
1292 pAction
= pAction
->GetPrev();
1295 pAction
= pThisTrack
->GetAction( nEndOwn
);
1296 while ( pAction
&& pAction
->GetActionNumber() >= nStartOwn
)
1298 aResolver
.HandleAction( pAction
, false /*bIsSharedAction*/,
1299 true /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1300 pAction
= pAction
->GetPrev();
1306 // merge shared changes into own document
1307 sal_uLong nStartShared
= pThisTrack
->GetActionMax() + 1;
1308 MergeDocument( rSharedDoc
, true, true );
1309 sal_uLong nEndShared
= pThisTrack
->GetActionMax();
1311 // only show changes from shared document
1312 aChangeViewSet
.SetShowChanges( true );
1313 aChangeViewSet
.SetShowAccepted( true );
1314 aChangeViewSet
.SetHasActionRange();
1315 aChangeViewSet
.SetTheActionRange( nStartShared
, nEndShared
);
1316 aDocument
.SetChangeViewSettings( aChangeViewSet
);
1323 ScopedVclPtrInstance
< InfoBox
> aInfoBox( GetActiveDialogParent(), ScGlobal::GetRscString( STR_DOC_UPDATED
) );
1324 aInfoBox
->Execute();
1327 return ( pThisAction
!= nullptr );
1330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */