Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / sc / source / ui / docshell / docsh3.cxx
blob72bdfadbebaf8839d7cafe433f71ab6acf35d797
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <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>
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 <memory>
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;
121 if ( nLockPart )
123 //! nExtFlags ???
124 pPaintLockData->AddRange( ScRange( nCol1, nRow1, nTab1,
125 nCol2, nRow2, nTab2 ), nLockPart );
128 nPart &= PAINT_EXTRAS; // for broadcasting
129 if (!nPart)
130 continue;
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 ) )
157 nCol1 = 0;
158 nCol2 = MAXCOL;
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();
243 if (xRangeList)
245 sal_uInt16 nParts = pPaint->GetParts();
246 for ( size_t i = 0, nCount = xRangeList->size(); i < nCount; i++ )
248 //! nExtFlags ???
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(),
252 nParts );
256 if ( pPaint->GetModified() )
257 SetDocumentModified();
259 delete pPaint;
262 else
264 OSL_FAIL("UnlockPaint ohne LockPaint");
268 void ScDocShell::LockDocument_Impl(sal_uInt16 nNew)
270 if (!nDocumentLock)
272 ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
273 if (pDrawLayer)
274 pDrawLayer->setLock(true);
276 nDocumentLock = nNew;
279 void ScDocShell::UnlockDocument_Impl(sal_uInt16 nNew)
281 nDocumentLock = nNew;
282 if (!nDocumentLock)
284 ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
285 if (pDrawLayer)
286 pDrawLayer->setLock(false);
290 void ScDocShell::SetLockCount(sal_uInt16 nNew)
292 if (nNew) // setzen
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()
325 if (nDocumentLock)
327 UnlockPaint_Impl(true);
328 UnlockDocument_Impl(nDocumentLock - 1);
330 else
332 OSL_FAIL("UnlockDocument without LockDocument");
336 void ScDocShell::SetInplace( bool bInplace )
338 if (bIsInplace != bInplace)
340 bIsInplace = bInplace;
341 CalcOutputFactor();
345 void ScDocShell::CalcOutputFactor()
347 if (bIsInplace)
349 nPrtToScreenFactor = 1.0; // passt sonst nicht zur inaktiven Darstellung
350 return;
353 bool bTextWysiwyg = SC_MOD()->GetInputOptions().GetTextWysiwyg();
354 if (bTextWysiwyg)
356 nPrtToScreenFactor = 1.0;
357 return;
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));
367 vcl::Font aDefFont;
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;
388 else
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;
400 bool bAutoSpell;
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() ) );
412 if (bForLoading)
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 );
453 CalcOutputFactor();
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 );
481 CalcOutputFactor();
483 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
484 UpdateFontList();
486 ScModule* pScMod = SC_MOD();
487 SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this );
488 while (pFrame)
490 SfxViewShell* pSh = pFrame->GetViewShell();
491 if (ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(pSh))
493 ScInputHandler* pInputHdl = pScMod->GetInputHdl(pViewSh);
494 if (pInputHdl)
495 pInputHdl->UpdateRefDevice();
497 pFrame = SfxViewFrame::GetNext( *pFrame, this );
501 else if (nDiffFlags & SfxPrinterChangeFlags::JOBSETUP)
503 SfxPrinter* pOldPrinter = aDocument.GetPrinter();
504 if (pOldPrinter)
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));
526 if (pStyleSheet)
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 );
541 // Groesse umdrehen
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);
558 return 0;
561 ScChangeAction* ScDocShell::GetChangeAction( const ScAddress& rPos )
563 ScChangeTrack* pTrack = GetDocument().GetChangeTrack();
564 if (!pTrack)
565 return nullptr;
567 SCTAB nTab = rPos.Tab();
569 const ScChangeAction* pFound = nullptr;
570 long nModified = 0;
571 const ScChangeAction* pAction = pTrack->GetFirst();
572 while (pAction)
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
591 ++nModified;
594 if ( pAction->GetType() == SC_CAT_MOVE )
596 ScRange aRange =
597 static_cast<const ScChangeActionMove*>(pAction)->
598 GetFromRange().MakeRange();
599 if ( aRange.In( rPos ) )
601 pFound = pAction;
602 ++nModified;
606 pAction = pAction->GetNext();
609 return const_cast<ScChangeAction*>(pFound);
612 void ScDocShell::SetChangeComment( ScChangeAction* pAction, const OUString& rComment )
614 if (pAction)
616 pAction->SetComment( rComment );
617 //! Undo ???
618 SetDocumentModified();
620 // Dialog-Notify
621 ScChangeTrack* pTrack = GetDocument().GetChangeTrack();
622 if (pTrack)
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 );
639 aDate += " ";
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,
646 0 );
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));
654 pDlg->Execute();
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();
668 OUString aOldUser;
669 pTrack = aDocument.GetChangeTrack();
670 if ( pTrack )
672 aOldUser = pTrack->GetUser();
674 // check if comparing to same document
676 OUString aThisFile;
677 const SfxMedium* pThisMed = GetMedium();
678 if (pThisMed)
679 aThisFile = pThisMed->GetName();
680 OUString aOtherFile;
681 SfxObjectShell* pOtherSh = rOtherDoc.GetDocumentShell();
682 if (pOtherSh)
684 const SfxMedium* pOtherMed = pOtherSh->GetMedium();
685 if (pOtherMed)
686 aOtherFile = pOtherMed->GetName();
688 bool bSameDoc = ( aThisFile == aOtherFile && !aThisFile.isEmpty() );
689 if ( !bSameDoc )
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();
711 if ( pTrack )
712 pTrack->SetUser( aOldUser );
714 PostPaintGridAll();
715 SetDocumentModified();
718 // Merge (Aenderungen zusammenfuehren)
720 static inline bool lcl_Equal( const ScChangeAction* pA, const ScChangeAction* pB, bool bIgnore100Sec )
722 return pA && pB &&
723 pA->GetActionNumber() == pB->GetActionNumber() &&
724 pA->GetType() == pB->GetType() &&
725 pA->GetUser() == pB->GetUser() &&
726 (bIgnore100Sec ?
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 )
736 return false;
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() &&
745 (bIgnore100Sec ?
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);
752 OUString aADesc;
753 pA->GetDescription(aADesc, pSearchDoc, true);
754 if (aActionDesc.equals(aADesc))
756 OSL_FAIL( "lcl_FindAction(): found equal action!" );
757 return true;
760 pA = pA->GetNext();
763 return false;
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
769 if (!pViewSh)
770 return;
772 ScChangeTrack* pSourceTrack = rOtherDoc.GetChangeTrack();
773 if (!pSourceTrack)
774 return; //! nichts zu tun - Fehlermeldung?
776 ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
777 if ( !pThisTrack )
778 { // anschalten
779 aDocument.StartChangeTracking();
780 pThisTrack = aDocument.GetChangeTrack();
781 OSL_ENSURE(pThisTrack,"ChangeTracking nicht angeschaltet?");
782 if ( !bShared )
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;
820 while ( pCount )
822 if ( bShared || !ScChangeTrack::MergeIgnore( *pCount, nFirstNewNumber ) )
823 ++nNewActionCount;
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();
845 switch ( eType )
847 case SC_CAT_INSERT_COLS :
848 case SC_CAT_INSERT_ROWS :
849 case SC_CAT_INSERT_TABS :
850 pSourceTrack->AppendInsert( pThisAction->GetBigRange().MakeRange() );
851 break;
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 );
864 break;
865 case SC_CAT_MOVE :
867 const ScChangeActionMove* pMove = static_cast<const ScChangeActionMove*>(pThisAction);
868 pSourceTrack->AppendMove( pMove->GetFromRange().MakeRange(),
869 pMove->GetBigRange().MakeRange(), nullptr );
871 break;
872 default:
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;
893 if ( bShared )
895 if ( !bCheckDuplicates || !lcl_FindAction( &rOtherDoc, pSourceAction, &aDocument, pFirstSearchAction, pLastSearchAction, bIgnore100Sec ) )
897 bMergeAction = true;
900 else
902 if ( !ScChangeTrack::MergeIgnore( *pSourceAction, nFirstNewNumber ) )
904 bMergeAction = true;
908 if ( bMergeAction )
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
921 OUString aValue;
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() );
928 #endif
930 else
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();
940 if ( nReject )
942 if ( bShared )
944 if ( nReject >= nFirstNewNumber )
946 nReject += nOffset;
948 ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
949 if ( pOldAction && pOldAction->IsVirgin() )
951 pThisTrack->Reject( pOldAction );
952 bHasRejected = true;
953 bExecute = false;
956 else
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
969 bExecute = false;
973 if ( bExecute )
975 // normal ausfuehren
976 ScRange aSourceRange = pSourceAction->GetBigRange().MakeRange();
977 rMarkData.SelectOneTable( aSourceRange.aStart.Tab() );
978 switch ( eSourceType )
980 case SC_CAT_CONTENT:
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;
987 OUString aValue;
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();
993 switch ( eMatrix )
995 case MM_NONE :
996 pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
997 break;
998 case MM_FORMULA :
1000 SCCOL nCols;
1001 SCROW nRows;
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 );
1010 break;
1011 case MM_REFERENCE : // do nothing
1012 break;
1015 break;
1016 case SC_CAT_INSERT_TABS :
1018 OUString aName;
1019 aDocument.CreateValidTabName( aName );
1020 GetDocFunc().InsertTable( aSourceRange.aStart.Tab(), aName, true, false );
1022 break;
1023 case SC_CAT_INSERT_ROWS:
1024 GetDocFunc().InsertCells( aSourceRange, nullptr, INS_INSROWS_BEFORE, true, false );
1025 break;
1026 case SC_CAT_INSERT_COLS:
1027 GetDocFunc().InsertCells( aSourceRange, nullptr, INS_INSCOLS_BEFORE, true, false );
1028 break;
1029 case SC_CAT_DELETE_TABS :
1030 GetDocFunc().DeleteTable( aSourceRange.aStart.Tab(), true, false );
1031 break;
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
1041 if ( bShared )
1043 ScChangeAction* pAct = pThisTrack->GetLast();
1044 if ( pAct && pAct->GetType() == eSourceType && pAct->IsDeletedIn() && !pSourceAction->IsDeletedIn() )
1046 pAct->RemoveAllDeletedIn();
1051 break;
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 );
1061 break;
1062 case SC_CAT_MOVE :
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 );
1069 break;
1070 default:
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 );
1082 else
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 );
1099 // fill merge map
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 )
1111 if ( bInverseMap )
1113 (*pMergeMap)[ nAction++ ] = nSourceAction++;
1115 else
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
1134 if (bHasRejected)
1135 PostPaintGridAll(); // Reject() paintet nicht selber
1137 UnlockPaint();
1140 bool ScDocShell::MergeSharedDocument( ScDocShell* pSharedDocShell )
1142 if ( !pSharedDocShell )
1144 return false;
1147 ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
1148 if ( !pThisTrack )
1150 return false;
1153 ScDocument& rSharedDoc = pSharedDocShell->GetDocument();
1154 ScChangeTrack* pSharedTrack = rSharedDoc.GetChangeTrack();
1155 if ( !pSharedTrack )
1157 return false;
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 )
1177 if ( pThisAction )
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 )
1185 OUString sTabName;
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 );
1192 delete pTmpDoc;
1193 sal_uLong nActStartOwn = nActEndShared + 1;
1194 sal_uLong nActEndOwn = pSharedTrack->GetActionMax();
1196 // find conflicts
1197 ScConflictsList aConflictsList;
1198 ScConflictsFinder aFinder( pSharedTrack, nActStartShared, nActEndShared, nActStartOwn, nActEndOwn, aConflictsList );
1199 if ( aFinder.Find() )
1201 ScConflictsListHelper::TransformConflictsList( aConflictsList, nullptr, &aOwnInverseMergeMap );
1202 bool bLoop = true;
1203 while ( bLoop )
1205 bLoop = false;
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 )
1213 return false;
1215 else
1217 bLoop = true;
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 )
1230 OUString sTabName;
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 );
1279 delete pTmpDoc;
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();
1304 else
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 );
1319 // update view
1320 PostPaintExtras();
1321 PostPaintGridAll();
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: */