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 <o3tl/unit_conversion.hxx>
29 #include <officecfg/Office/Common.hxx>
30 #include <sal/log.hxx>
31 #include <sfx2/viewfrm.hxx>
32 #include <sfx2/app.hxx>
33 #include <sfx2/docfile.hxx>
34 #include <sfx2/printer.hxx>
35 #include <svl/numformat.hxx>
36 #include <svx/pageitem.hxx>
37 #include <svx/postattr.hxx>
38 #include <svx/svxids.hrc>
39 #include <unotools/configmgr.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/virdev.hxx>
42 #include <vcl/weld.hxx>
43 #include <osl/diagnose.h>
46 #include "docshimp.hxx"
48 #include <tabvwsh.hxx>
49 #include <viewdata.hxx>
50 #include <docpool.hxx>
51 #include <stlpool.hxx>
52 #include <patattr.hxx>
53 #include <uiitems.hxx>
55 #include <docoptio.hxx>
56 #include <viewopti.hxx>
57 #include <pntlock.hxx>
58 #include <chgtrack.hxx>
59 #include <docfunc.hxx>
60 #include <formulacell.hxx>
61 #include <chgviset.hxx>
62 #include <progress.hxx>
64 #include <inputopt.hxx>
65 #include <drwlayer.hxx>
66 #include <inputhdl.hxx>
67 #include <conflictsdlg.hxx>
68 #include <globstr.hrc>
69 #include <scresid.hxx>
70 #include <markdata.hxx>
72 #include <formulaopt.hxx>
74 #include <comphelper/lok.hxx>
75 #include <sfx2/lokhelper.hxx>
77 // Redraw - Notifications
79 void ScDocShell::PostEditView( ScEditEngineDefaulter
* pEditEngine
, const ScAddress
& rCursorPos
)
81 // Broadcast( ScEditViewHint( pEditEngine, rCursorPos ) );
83 // Test: only active ViewShell
85 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
86 if (pViewSh
&& pViewSh
->GetViewData().GetDocShell() == this)
88 ScEditViewHint
aHint( pEditEngine
, rCursorPos
);
89 pViewSh
->Notify( *this, aHint
);
93 void ScDocShell::PostDataChanged()
95 Broadcast( SfxHint( SfxHintId::ScDataChanged
) );
96 SfxGetpApp()->Broadcast(SfxHint( SfxHintId::ScAnyDataChanged
)); // Navigator
97 m_pDocument
->PrepareFormulaCalc();
98 //! notify navigator directly!
101 void ScDocShell::PostPaint( SCCOL nStartCol
, SCROW nStartRow
, SCTAB nStartTab
,
102 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nEndTab
, PaintPartFlags nPart
,
103 sal_uInt16 nExtFlags
, tools::Long nMaxWidthAffectedHint
)
105 ScRange
aRange(nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
);
106 PostPaint(aRange
, nPart
, nExtFlags
, nMaxWidthAffectedHint
);
109 void ScDocShell::PostPaint( const ScRangeList
& rRanges
, PaintPartFlags nPart
, sal_uInt16 nExtFlags
, tools::Long nMaxWidthAffectedHint
)
111 ScRangeList aPaintRanges
;
112 std::set
<SCTAB
> aTabsInvalidated
;
113 const SCTAB nMaxTab
= m_pDocument
->GetTableCount() - 1;
114 for (size_t i
= 0, n
= rRanges
.size(); i
< n
; ++i
)
116 const ScRange
& rRange
= rRanges
[i
];
117 SCCOL nCol1
= rRange
.aStart
.Col(), nCol2
= rRange
.aEnd
.Col();
118 SCROW nRow1
= rRange
.aStart
.Row(), nRow2
= rRange
.aEnd
.Row();
119 SCTAB nTab1
= rRange
.aStart
.Tab(), nTab2
= std::min
<SCTAB
>(nMaxTab
, rRange
.aEnd
.Tab());
121 if (nTab1
< 0 || nTab2
< 0)
124 if (!m_pDocument
->ValidCol(nCol1
))
126 nMaxWidthAffectedHint
= -1; // Hint no longer valid
127 nCol1
= m_pDocument
->MaxCol();
129 if (!m_pDocument
->ValidRow(nRow1
)) nRow1
= m_pDocument
->MaxRow();
130 if (!m_pDocument
->ValidCol(nCol2
))
132 nMaxWidthAffectedHint
= -1; // Hint no longer valid
133 nCol2
= m_pDocument
->MaxCol();
135 if (!m_pDocument
->ValidRow(nRow2
)) nRow2
= m_pDocument
->MaxRow();
137 if ( m_pPaintLockData
)
139 // #i54081# PaintPartFlags::Extras still has to be broadcast because it changes the
140 // current sheet if it's invalid. All other flags added to pPaintLockData.
141 PaintPartFlags nLockPart
= nPart
& ~PaintPartFlags::Extras
;
142 if ( nLockPart
!= PaintPartFlags::NONE
)
145 m_pPaintLockData
->AddRange( ScRange( nCol1
, nRow1
, nTab1
,
146 nCol2
, nRow2
, nTab2
), nLockPart
);
149 nPart
&= PaintPartFlags::Extras
; // for broadcasting
150 if (nPart
== PaintPartFlags::NONE
)
154 if (nExtFlags
& SC_PF_LINES
) // respect space for lines
156 //! check for hidden columns/rows!
159 nMaxWidthAffectedHint
= -1; // Hint no longer valid
162 if (nCol2
< m_pDocument
->MaxCol())
164 nMaxWidthAffectedHint
= -1; // Hint no longer valid
167 if (nRow1
>0) --nRow1
;
168 if (nRow2
<m_pDocument
->MaxRow()) ++nRow2
;
171 // expand for the merged ones
172 if (nExtFlags
& SC_PF_TESTMERGE
)
173 m_pDocument
->ExtendMerge( nCol1
, nRow1
, nCol2
, nRow2
, nTab1
);
175 if ( nCol1
!= 0 || nCol2
!= m_pDocument
->MaxCol() )
177 // Extend to whole rows if SC_PF_WHOLEROWS is set, or rotated or non-left
178 // aligned cells are contained (see UpdatePaintExt).
179 // Special handling for RTL text (#i9731#) is unnecessary now with full
180 // support of right-aligned text.
182 if ( ( nExtFlags
& SC_PF_WHOLEROWS
) ||
183 m_pDocument
->HasAttrib( nCol1
,nRow1
,nTab1
,
184 m_pDocument
->MaxCol(),nRow2
,nTab2
, HasAttrFlags::Rotate
| HasAttrFlags::RightOrCenter
) )
187 nCol2
= m_pDocument
->MaxCol();
188 nMaxWidthAffectedHint
= -1; // Hint no longer valid
191 aPaintRanges
.push_back(ScRange(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
));
192 for (auto nTabNum
= nTab1
; nTabNum
<= nTab2
; ++nTabNum
)
193 aTabsInvalidated
.insert(nTabNum
);
196 Broadcast(ScPaintHint(aPaintRanges
.Combine(), nPart
, nMaxWidthAffectedHint
));
198 // LOK: we are supposed to update the row / columns headers (and actually
199 // the document size too - cell size affects that, obviously)
200 if ((nPart
& (PaintPartFlags::Top
| PaintPartFlags::Left
)) && comphelper::LibreOfficeKit::isActive())
202 ScModelObj
* pModel
= GetModel();
203 for (auto nTab
: aTabsInvalidated
)
204 SfxLokHelper::notifyPartSizeChangedAllViews(pModel
, nTab
);
208 void ScDocShell::PostPaintGridAll()
210 PostPaint( 0,0,0, m_pDocument
->MaxCol(),m_pDocument
->MaxRow(),MAXTAB
, PaintPartFlags::Grid
);
213 void ScDocShell::PostPaintCell( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, tools::Long nMaxWidthAffectedHint
)
215 PostPaint( nCol
,nRow
,nTab
, nCol
,nRow
,nTab
, PaintPartFlags::Grid
, SC_PF_TESTMERGE
, nMaxWidthAffectedHint
);
218 void ScDocShell::PostPaintCell( const ScAddress
& rPos
, tools::Long nMaxWidthAffectedHint
)
220 PostPaintCell( rPos
.Col(), rPos
.Row(), rPos
.Tab(), nMaxWidthAffectedHint
);
223 void ScDocShell::PostPaintExtras()
225 PostPaint( 0,0,0, m_pDocument
->MaxCol(),m_pDocument
->MaxRow(),MAXTAB
, PaintPartFlags::Extras
);
228 void ScDocShell::UpdatePaintExt( sal_uInt16
& rExtFlags
, const ScRange
& rRange
)
230 if ( ( rExtFlags
& SC_PF_LINES
) == 0 &&
231 m_pDocument
->HasAttrib( rRange
, HasAttrFlags::Lines
| HasAttrFlags::Shadow
| HasAttrFlags::Conditional
) )
233 // If the range contains lines, shadow or conditional formats,
234 // set SC_PF_LINES to include one extra cell in all directions.
236 rExtFlags
|= SC_PF_LINES
;
239 if ( ( rExtFlags
& SC_PF_WHOLEROWS
) == 0 &&
240 ( rRange
.aStart
.Col() != 0 || rRange
.aEnd
.Col() != m_pDocument
->MaxCol() ) &&
241 m_pDocument
->HasAttrib( rRange
, HasAttrFlags::Rotate
| HasAttrFlags::RightOrCenter
) )
243 // If the range contains (logically) right- or center-aligned cells,
244 // or rotated cells, set SC_PF_WHOLEROWS to paint the whole rows.
245 // This test isn't needed after the cell changes, because it's also
246 // tested in PostPaint. UpdatePaintExt may later be changed to do this
247 // only if called before the changes.
249 rExtFlags
|= SC_PF_WHOLEROWS
;
253 void ScDocShell::UpdatePaintExt( sal_uInt16
& rExtFlags
, SCCOL nStartCol
, SCROW nStartRow
, SCTAB nStartTab
,
254 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nEndTab
)
256 UpdatePaintExt( rExtFlags
, ScRange( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
) );
259 void ScDocShell::LockPaint_Impl(bool bDoc
)
261 if ( !m_pPaintLockData
)
262 m_pPaintLockData
.reset( new ScPaintLockData
);
263 m_pPaintLockData
->IncLevel(bDoc
);
266 void ScDocShell::UnlockPaint_Impl(bool bDoc
)
268 if ( m_pPaintLockData
)
270 if ( m_pPaintLockData
->GetLevel(bDoc
) )
271 m_pPaintLockData
->DecLevel(bDoc
);
272 if (!m_pPaintLockData
->GetLevel(!bDoc
) && !m_pPaintLockData
->GetLevel(bDoc
))
276 // don't continue collecting
277 std::unique_ptr
<ScPaintLockData
> pPaint
= std::move(m_pPaintLockData
);
279 ScRangeListRef xRangeList
= pPaint
->GetRangeList();
280 if ( xRangeList
.is() )
282 PaintPartFlags nParts
= pPaint
->GetParts();
283 for ( size_t i
= 0, nCount
= xRangeList
->size(); i
< nCount
; i
++ )
286 ScRange
const & rRange
= (*xRangeList
)[i
];
287 PostPaint( rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aStart
.Tab(),
288 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rRange
.aEnd
.Tab(),
293 if ( pPaint
->GetModified() )
294 SetDocumentModified();
299 OSL_FAIL("UnlockPaint without LockPaint");
303 void ScDocShell::LockDocument_Impl(sal_uInt16 nNew
)
305 if (!m_nDocumentLock
)
307 ScDrawLayer
* pDrawLayer
= m_pDocument
->GetDrawLayer();
309 pDrawLayer
->setLock(true);
311 m_nDocumentLock
= nNew
;
314 void ScDocShell::UnlockDocument_Impl(sal_uInt16 nNew
)
316 m_nDocumentLock
= nNew
;
317 if (!m_nDocumentLock
)
319 ScDrawLayer
* pDrawLayer
= m_pDocument
->GetDrawLayer();
321 pDrawLayer
->setLock(false);
325 void ScDocShell::SetLockCount(sal_uInt16 nNew
)
329 if ( !m_pPaintLockData
)
330 m_pPaintLockData
.reset( new ScPaintLockData
);
331 m_pPaintLockData
->SetDocLevel(nNew
-1);
332 LockDocument_Impl(nNew
);
334 else if (m_pPaintLockData
) // delete
336 m_pPaintLockData
->SetDocLevel(0); // at unlock, execute immediately
337 UnlockPaint_Impl(true); // now
338 UnlockDocument_Impl(0);
342 void ScDocShell::LockPaint()
344 LockPaint_Impl(false);
347 void ScDocShell::UnlockPaint()
349 UnlockPaint_Impl(false);
352 void ScDocShell::LockDocument()
354 LockPaint_Impl(true);
355 LockDocument_Impl(m_nDocumentLock
+ 1);
358 void ScDocShell::UnlockDocument()
362 UnlockPaint_Impl(true);
363 UnlockDocument_Impl(m_nDocumentLock
- 1);
367 OSL_FAIL("UnlockDocument without LockDocument");
371 void ScDocShell::SetInplace( bool bInplace
)
373 if (m_bIsInplace
!= bInplace
)
375 m_bIsInplace
= bInplace
;
380 void ScDocShell::CalcOutputFactor()
384 m_nPrtToScreenFactor
= 1.0; // otherwise it does not match the inactive display
388 bool bTextWysiwyg
= ScModule::get()->GetInputOptions().GetTextWysiwyg();
391 m_nPrtToScreenFactor
= 1.0;
395 OUString
aTestString(
396 u
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789"_ustr
);
397 tools::Long nPrinterWidth
= 0;
398 const ScPatternAttr
& rPattern(m_pDocument
->getCellAttributeHelper().getDefaultCellAttribute());
401 OutputDevice
* pRefDev
= GetRefDevice();
402 MapMode aOldMode
= pRefDev
->GetMapMode();
403 vcl::Font aOldFont
= pRefDev
->GetFont();
405 pRefDev
->SetMapMode(MapMode(MapUnit::MapPixel
));
406 rPattern
.fillFontOnly(aDefFont
, pRefDev
); // font color doesn't matter here
407 pRefDev
->SetFont(aDefFont
);
408 nPrinterWidth
= pRefDev
->PixelToLogic(Size(pRefDev
->GetTextWidth(aTestString
), 0), MapMode(MapUnit::Map100thMM
)).Width();
409 pRefDev
->SetFont(aOldFont
);
410 pRefDev
->SetMapMode(aOldMode
);
412 ScopedVclPtrInstance
< VirtualDevice
> pVirtWindow( *Application::GetDefaultDevice() );
413 pVirtWindow
->SetMapMode(MapMode(MapUnit::MapPixel
));
414 rPattern
.fillFontOnly(aDefFont
, pVirtWindow
); // font color doesn't matter here
415 pVirtWindow
->SetFont(aDefFont
);
416 double nWindowWidth
= pVirtWindow
->GetTextWidth(aTestString
) / ScGlobal::nScreenPPTX
;
417 nWindowWidth
= o3tl::convert(nWindowWidth
, o3tl::Length::twip
, o3tl::Length::mm100
);
419 if (nPrinterWidth
&& nWindowWidth
)
420 m_nPrtToScreenFactor
= nPrinterWidth
/ nWindowWidth
;
423 OSL_FAIL("GetTextSize returns 0 ??");
424 m_nPrtToScreenFactor
= 1.0;
428 void ScDocShell::InitOptions(bool bForLoading
) // called from InitNew and Load
430 // Settings from the SpellCheckCfg get into Doc- and ViewOptions
432 LanguageType nDefLang
, nCjkLang
, nCtlLang
;
433 ScModule::GetSpellSettings( nDefLang
, nCjkLang
, nCtlLang
);
434 ScModule
* pScMod
= ScModule::get();
436 ScDocOptions aDocOpt
= pScMod
->GetDocOptions();
437 ScFormulaOptions aFormulaOpt
= pScMod
->GetFormulaOptions();
438 ScViewOptions aViewOpt
= pScMod
->GetViewOptions();
440 if (!comphelper::IsFuzzing())
442 // two-digit year entry from Tools->Options->General
443 aDocOpt
.SetYear2000(officecfg::Office::Common::DateFormat::TwoDigitYear::get());
448 // #i112123# No style:decimal-places attribute means automatic decimals, not the configured default,
449 // so it must not be taken from the global options.
450 // Calculation settings are handled separately in ScXMLBodyContext::EndElement.
451 aDocOpt
.SetStdPrecision( SvNumberFormatter::UNLIMITED_PRECISION
);
453 // fdo#78294 The default null-date if
454 // <table:null-date table:date-value='...' />
455 // is absent is 1899-12-30 regardless what the configuration is set to.
456 // Import filters may override this value.
457 aDocOpt
.SetDate( 30, 12, 1899);
460 m_pDocument
->SetDocOptions( aDocOpt
);
461 m_pDocument
->SetViewOptions( aViewOpt
);
462 SetFormulaOptions( aFormulaOpt
, bForLoading
);
464 // print options are now set directly before the printing
466 m_pDocument
->SetLanguage( nDefLang
, nCjkLang
, nCtlLang
);
469 Printer
* ScDocShell::GetDocumentPrinter() // for OLE
471 return m_pDocument
->GetPrinter();
474 SfxPrinter
* ScDocShell::GetPrinter(bool bCreateIfNotExist
)
476 return m_pDocument
->GetPrinter(bCreateIfNotExist
);
479 void ScDocShell::UpdateFontList()
481 // pImpl->pFontList = new FontList( GetPrinter(), Application::GetDefaultDevice() );
482 m_pImpl
->pFontList
.reset(new FontList(GetRefDevice(), nullptr));
483 SvxFontListItem
aFontListItem( m_pImpl
->pFontList
.get(), SID_ATTR_CHAR_FONTLIST
);
484 PutItem( aFontListItem
);
489 OutputDevice
* ScDocShell::GetRefDevice()
491 return m_pDocument
->GetRefDevice();
494 sal_uInt16
ScDocShell::SetPrinter( VclPtr
<SfxPrinter
> const & pNewPrinter
, SfxPrinterChangeFlags nDiffFlags
)
496 SfxPrinter
*pOld
= m_pDocument
->GetPrinter( false );
497 if ( pOld
&& pOld
->IsPrinting() )
498 return SFX_PRINTERROR_BUSY
;
500 if (nDiffFlags
& SfxPrinterChangeFlags::PRINTER
)
502 if ( m_pDocument
->GetPrinter() != pNewPrinter
)
504 m_pDocument
->SetPrinter( pNewPrinter
);
505 m_pDocument
->SetPrintOptions();
507 // MT: Use UpdateFontList: Will use Printer fonts only if needed!
509 delete pImpl->pFontList;
510 pImpl->pFontList = new FontList( pNewPrinter, Application::GetDefaultDevice() );
511 SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
512 PutItem( aFontListItem );
516 ScModule
* pScMod
= ScModule::get();
517 if (pScMod
->GetInputOptions().GetTextWysiwyg())
520 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst( this );
523 SfxViewShell
* pSh
= pFrame
->GetViewShell();
524 if (ScTabViewShell
* pViewSh
= dynamic_cast<ScTabViewShell
*>(pSh
))
526 ScInputHandler
* pInputHdl
= pScMod
->GetInputHdl(pViewSh
);
528 pInputHdl
->UpdateRefDevice();
530 pFrame
= SfxViewFrame::GetNext( *pFrame
, this );
534 else if (nDiffFlags
& SfxPrinterChangeFlags::JOBSETUP
)
536 SfxPrinter
* pOldPrinter
= m_pDocument
->GetPrinter();
539 pOldPrinter
->SetJobSetup( pNewPrinter
->GetJobSetup() );
541 // #i6706# Call SetPrinter with the old printer again, so the drawing layer
542 // RefDevice is set (calling ReformatAllTextObjects and rebuilding charts),
543 // because the JobSetup (printer device settings) may affect text layout.
544 m_pDocument
->SetPrinter( pOldPrinter
);
545 CalcOutputFactor(); // also with the new settings
549 if (nDiffFlags
& SfxPrinterChangeFlags::OPTIONS
)
551 m_pDocument
->SetPrintOptions(); //! from new printer ???
554 if (nDiffFlags
& (SfxPrinterChangeFlags::CHG_ORIENTATION
| SfxPrinterChangeFlags::CHG_SIZE
))
556 OUString aStyle
= m_pDocument
->GetPageStyle( GetCurTab() );
557 ScStyleSheetPool
* pStPl
= m_pDocument
->GetStyleSheetPool();
558 SfxStyleSheet
* pStyleSheet
= static_cast<SfxStyleSheet
*>(pStPl
->Find(aStyle
, SfxStyleFamily::Page
));
561 SfxItemSet
& rSet
= pStyleSheet
->GetItemSet();
563 if (nDiffFlags
& SfxPrinterChangeFlags::CHG_ORIENTATION
)
565 const SvxPageItem
& rOldItem
= rSet
.Get(ATTR_PAGE
);
566 bool bWasLand
= rOldItem
.IsLandscape();
567 bool bNewLand
= ( pNewPrinter
->GetOrientation() == Orientation::Landscape
);
568 if (bNewLand
!= bWasLand
)
570 SvxPageItem
aNewItem( rOldItem
);
571 aNewItem
.SetLandscape( bNewLand
);
572 rSet
.Put( aNewItem
);
575 Size aOldSize
= rSet
.Get(ATTR_PAGE_SIZE
).GetSize();
576 // coverity[swapped_arguments : FALSE] - this is in the correct order
577 Size
aNewSize(aOldSize
.Height(),aOldSize
.Width());
578 SvxSizeItem
aNewSItem(ATTR_PAGE_SIZE
,aNewSize
);
579 rSet
.Put( aNewSItem
);
582 if (nDiffFlags
& SfxPrinterChangeFlags::CHG_SIZE
)
584 SvxSizeItem
aPaperSizeItem( ATTR_PAGE_SIZE
, SvxPaperInfo::GetPaperSize(pNewPrinter
) );
585 rSet
.Put( aPaperSizeItem
);
590 PostPaint(0,0,0,m_pDocument
->MaxCol(),m_pDocument
->MaxRow(),MAXTAB
,PaintPartFlags::All
);
595 ScChangeAction
* ScDocShell::GetChangeAction( const ScAddress
& rPos
)
597 ScChangeTrack
* pTrack
= GetDocument().GetChangeTrack();
601 SCTAB nTab
= rPos
.Tab();
603 const ScChangeAction
* pFound
= nullptr;
604 const ScChangeAction
* pAction
= pTrack
->GetFirst();
607 ScChangeActionType eType
= pAction
->GetType();
608 //! ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc )...
609 if ( pAction
->IsVisible() && eType
!= SC_CAT_DELETE_TABS
)
611 const ScBigRange
& rBig
= pAction
->GetBigRange();
612 if ( rBig
.aStart
.Tab() == nTab
)
614 ScRange aRange
= rBig
.MakeRange( GetDocument() );
616 if ( eType
== SC_CAT_DELETE_ROWS
)
617 aRange
.aEnd
.SetRow( aRange
.aStart
.Row() );
618 else if ( eType
== SC_CAT_DELETE_COLS
)
619 aRange
.aEnd
.SetCol( aRange
.aStart
.Col() );
621 if ( aRange
.Contains( rPos
) )
623 pFound
= pAction
; // the last one wins
626 if ( pAction
->GetType() == SC_CAT_MOVE
)
629 static_cast<const ScChangeActionMove
*>(pAction
)->
630 GetFromRange().MakeRange( GetDocument() );
631 if ( aRange
.Contains( rPos
) )
637 pAction
= pAction
->GetNext();
640 return const_cast<ScChangeAction
*>(pFound
);
643 void ScDocShell::SetChangeComment( ScChangeAction
* pAction
, const OUString
& rComment
)
648 pAction
->SetComment( rComment
);
650 SetDocumentModified();
653 ScChangeTrack
* pTrack
= GetDocument().GetChangeTrack();
656 sal_uLong nNumber
= pAction
->GetActionNumber();
657 pTrack
->NotifyModified( ScChangeTrackMsgType::Change
, nNumber
, nNumber
);
661 void ScDocShell::ExecuteChangeCommentDialog( ScChangeAction
* pAction
, weld::Window
* pParent
, bool bPrevNext
)
663 if (!pAction
) return; // without action is nothing...
665 OUString aComment
= pAction
->GetComment();
666 OUString aAuthor
= pAction
->GetUser();
668 DateTime aDT
= pAction
->GetDateTime();
669 OUString aDate
= ScGlobal::getLocaleData().getDate( aDT
) + " " +
670 ScGlobal::getLocaleData().getTime( aDT
, false );
672 SfxItemSetFixed
<SID_ATTR_POSTIT_AUTHOR
, SID_ATTR_POSTIT_TEXT
> aSet( GetPool() );
674 aSet
.Put( SvxPostItTextItem ( aComment
, SID_ATTR_POSTIT_TEXT
) );
675 aSet
.Put( SvxPostItAuthorItem( aAuthor
, SID_ATTR_POSTIT_AUTHOR
) );
676 aSet
.Put( SvxPostItDateItem ( aDate
, SID_ATTR_POSTIT_DATE
) );
678 std::unique_ptr
<ScRedComDialog
> pDlg(new ScRedComDialog( pParent
, aSet
,this,pAction
,bPrevNext
));
683 void ScDocShell::CompareDocument( ScDocument
& rOtherDoc
)
685 ScChangeTrack
* pTrack
= m_pDocument
->GetChangeTrack();
686 if ( pTrack
&& pTrack
->GetFirst() )
688 //! there are changes -> inquiry if needs to be deleted
691 m_pDocument
->EndChangeTracking();
692 m_pDocument
->StartChangeTracking();
695 pTrack
= m_pDocument
->GetChangeTrack();
698 aOldUser
= pTrack
->GetUser();
700 // check if comparing to same document
703 const SfxMedium
* pThisMed
= GetMedium();
705 aThisFile
= pThisMed
->GetName();
707 ScDocShell
* pOtherSh
= rOtherDoc
.GetDocumentShell();
710 const SfxMedium
* pOtherMed
= pOtherSh
->GetMedium();
712 aOtherFile
= pOtherMed
->GetName();
714 bool bSameDoc
= ( aThisFile
== aOtherFile
&& !aThisFile
.isEmpty() );
717 // create change actions from comparing with the name of the user
718 // who last saved the document
719 // (only if comparing different documents)
721 using namespace ::com::sun::star
;
722 uno::Reference
<document::XDocumentProperties
> xDocProps(
723 GetModel()->getDocumentProperties());
724 OSL_ENSURE(xDocProps
.is(), "no DocumentProperties");
725 OUString aDocUser
= xDocProps
->getModifiedBy();
727 if ( !aDocUser
.isEmpty() )
728 pTrack
->SetUser( aDocUser
);
732 m_pDocument
->CompareDocument( rOtherDoc
);
734 pTrack
= m_pDocument
->GetChangeTrack();
736 pTrack
->SetUser( aOldUser
);
739 SetDocumentModified();
742 // Merge (combine documents)
744 static bool lcl_Equal( const ScChangeAction
* pA
, const ScChangeAction
* pB
, bool bIgnore100Sec
)
747 pA
->GetActionNumber() == pB
->GetActionNumber() &&
748 pA
->GetType() == pB
->GetType() &&
749 pA
->GetUser() == pB
->GetUser() &&
751 pA
->GetDateTimeUTC().IsEqualIgnoreNanoSec( pB
->GetDateTimeUTC() ) :
752 pA
->GetDateTimeUTC() == pB
->GetDateTimeUTC());
753 // don't compare state if an old change has been accepted
756 static bool lcl_FindAction( ScDocument
& rDoc
, const ScChangeAction
* pAction
, ScDocument
& rSearchDoc
, const ScChangeAction
* pFirstSearchAction
, const ScChangeAction
* pLastSearchAction
, bool bIgnore100Sec
)
758 if ( !pAction
|| !pFirstSearchAction
|| !pLastSearchAction
)
763 sal_uLong nLastSearchAction
= pLastSearchAction
->GetActionNumber();
764 const ScChangeAction
* pA
= pFirstSearchAction
;
765 while ( pA
&& pA
->GetActionNumber() <= nLastSearchAction
)
767 if ( pAction
->GetType() == pA
->GetType() &&
768 pAction
->GetUser() == pA
->GetUser() &&
770 pAction
->GetDateTimeUTC().IsEqualIgnoreNanoSec( pA
->GetDateTimeUTC() ) :
771 pAction
->GetDateTimeUTC() == pA
->GetDateTimeUTC() ) &&
772 pAction
->GetBigRange() == pA
->GetBigRange() )
774 OUString aActionDesc
= pAction
->GetDescription(rDoc
, true);
775 OUString aADesc
= pA
->GetDescription(rSearchDoc
, true);
776 if (aActionDesc
== aADesc
)
778 OSL_FAIL( "lcl_FindAction(): found equal action!" );
788 void ScDocShell::MergeDocument( ScDocument
& rOtherDoc
, bool bShared
, bool bCheckDuplicates
, sal_uLong nOffset
, ScChangeActionMergeMap
* pMergeMap
, bool bInverseMap
)
790 ScTabViewShell
* pViewSh
= GetBestViewShell( false ); //! functions to the DocShell
794 ScChangeTrack
* pSourceTrack
= rOtherDoc
.GetChangeTrack();
796 return; //! nothing to do - error notification?
798 ScChangeTrack
* pThisTrack
= m_pDocument
->GetChangeTrack();
801 m_pDocument
->StartChangeTracking();
802 pThisTrack
= m_pDocument
->GetChangeTrack();
803 OSL_ENSURE(pThisTrack
,"ChangeTracking not enabled?");
806 // turn on visual RedLining
807 ScChangeViewSettings aChangeViewSet
;
808 aChangeViewSet
.SetShowChanges(true);
809 m_pDocument
->SetChangeViewSettings(aChangeViewSet
);
813 // include Nano seconds in compare?
814 bool bIgnore100Sec
= !pSourceTrack
->IsTimeNanoSeconds() ||
815 !pThisTrack
->IsTimeNanoSeconds();
817 // find common initial position
818 sal_uLong nFirstNewNumber
= 0;
819 const ScChangeAction
* pSourceAction
= pSourceTrack
->GetFirst();
820 const ScChangeAction
* pThisAction
= pThisTrack
->GetFirst();
821 // skip identical actions
822 while ( lcl_Equal( pSourceAction
, pThisAction
, bIgnore100Sec
) )
824 nFirstNewNumber
= pSourceAction
->GetActionNumber() + 1;
825 pSourceAction
= pSourceAction
->GetNext();
826 pThisAction
= pThisAction
->GetNext();
828 // pSourceAction and pThisAction now point to the first "own" actions
829 // The common actions before don't interest at all
831 //! Inquiry if the documents where equal before the change tracking !!!
833 const ScChangeAction
* pFirstMergeAction
= pSourceAction
;
834 const ScChangeAction
* pFirstSearchAction
= pThisAction
;
836 // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
837 const ScChangeAction
* pLastSearchAction
= pThisTrack
->GetLast();
839 // Create MergeChangeData from the following actions
840 sal_uLong nNewActionCount
= 0;
841 const ScChangeAction
* pCount
= pSourceAction
;
844 if ( bShared
|| !ScChangeTrack::MergeIgnore( *pCount
, nFirstNewNumber
) )
846 pCount
= pCount
->GetNext();
848 if (!nNewActionCount
)
849 return; //! nothing to do - error notification?
850 // from here on no return
852 ScProgress
aProgress( this, u
"..."_ustr
, nNewActionCount
, true );
854 sal_uLong nLastMergeAction
= pSourceTrack
->GetLast()->GetActionNumber();
855 // UpdateReference-Undo, valid references for the last common state
856 pSourceTrack
->MergePrepare( pFirstMergeAction
, bShared
);
858 // adjust MergeChangeData to all yet following actions in this document
859 // -> references valid for this document
860 while ( pThisAction
)
862 // #i87049# [Collaboration] Conflict between delete row and insert content is not merged correctly
863 if ( !bShared
|| !ScChangeTrack::MergeIgnore( *pThisAction
, nFirstNewNumber
) )
865 ScChangeActionType eType
= pThisAction
->GetType();
868 case SC_CAT_INSERT_COLS
:
869 case SC_CAT_INSERT_ROWS
:
870 case SC_CAT_INSERT_TABS
:
871 pSourceTrack
->AppendInsert( pThisAction
->GetBigRange().MakeRange( GetDocument() ) );
873 case SC_CAT_DELETE_COLS
:
874 case SC_CAT_DELETE_ROWS
:
875 case SC_CAT_DELETE_TABS
:
877 const ScChangeActionDel
* pDel
= static_cast<const ScChangeActionDel
*>(pThisAction
);
878 if ( pDel
->IsTopDelete() && !pDel
->IsTabDeleteCol() )
879 { // deleted table contains deleted cols, which are not
880 sal_uLong nStart
, nEnd
;
881 pSourceTrack
->AppendDeleteRange(
882 pDel
->GetOverAllRange().MakeRange( GetDocument() ), nullptr, nStart
, nEnd
);
888 const ScChangeActionMove
* pMove
= static_cast<const ScChangeActionMove
*>(pThisAction
);
889 pSourceTrack
->AppendMove( pMove
->GetFromRange().MakeRange( GetDocument() ),
890 pMove
->GetBigRange().MakeRange( GetDocument() ), nullptr );
895 // added to avoid warnings
899 pThisAction
= pThisAction
->GetNext();
902 LockPaint(); // #i73877# no repainting after each action
904 // take over MergeChangeData into the current document
905 bool bHasRejected
= false;
906 OUString aOldUser
= pThisTrack
->GetUser();
907 pThisTrack
->SetUseFixDateTime( true );
908 ScMarkData
& rMarkData
= pViewSh
->GetViewData().GetMarkData();
909 ScMarkData
aOldMarkData( rMarkData
);
910 pSourceAction
= pFirstMergeAction
;
911 while ( pSourceAction
&& pSourceAction
->GetActionNumber() <= nLastMergeAction
)
913 bool bMergeAction
= false;
916 if ( !bCheckDuplicates
|| !lcl_FindAction( rOtherDoc
, pSourceAction
, *m_pDocument
, pFirstSearchAction
, pLastSearchAction
, bIgnore100Sec
) )
923 if ( !ScChangeTrack::MergeIgnore( *pSourceAction
, nFirstNewNumber
) )
931 ScChangeActionType eSourceType
= pSourceAction
->GetType();
932 if ( !bShared
&& pSourceAction
->IsDeletedIn() )
934 //! does it need to be determined yet if really deleted in
937 // lies in a range, which was deleted in this document
939 //! ??? revert deletion action ???
940 //! ??? save action somewhere else ???
941 #if OSL_DEBUG_LEVEL > 0
943 if ( eSourceType
== SC_CAT_CONTENT
)
944 aValue
= static_cast<const ScChangeActionContent
*>(pSourceAction
)->GetNewString( m_pDocument
.get() );
945 SAL_WARN( "sc", aValue
<< " omitted");
950 //! Take over date/author/comment of the source action!
952 pThisTrack
->SetUser( pSourceAction
->GetUser() );
953 pThisTrack
->SetFixDateTimeUTC( pSourceAction
->GetDateTimeUTC() );
954 sal_uLong nOldActionMax
= pThisTrack
->GetActionMax();
956 bool bExecute
= true;
957 sal_uLong nReject
= pSourceAction
->GetRejectAction();
962 if ( nReject
>= nFirstNewNumber
)
966 ScChangeAction
* pOldAction
= pThisTrack
->GetAction( nReject
);
967 if ( pOldAction
&& pOldAction
->IsVirgin() )
969 pThisTrack
->Reject( pOldAction
);
976 // decline old action (of the common ones)
977 ScChangeAction
* pOldAction
= pThisTrack
->GetAction( nReject
);
978 if (pOldAction
&& pOldAction
->GetState() == SC_CAS_VIRGIN
)
980 //! what happens at actions, which were accepted in this document???
981 //! error notification or what???
982 //! or execute reject change normally
984 pThisTrack
->Reject(pOldAction
);
985 bHasRejected
= true; // for Paint
994 ScRange aSourceRange
= pSourceAction
->GetBigRange().MakeRange( GetDocument() );
995 rMarkData
.SelectOneTable( aSourceRange
.aStart
.Tab() );
996 switch ( eSourceType
)
1000 //! Test if it was at the very bottom in the document, then automatic
1003 OSL_ENSURE( aSourceRange
.aStart
== aSourceRange
.aEnd
, "huch?" );
1004 ScAddress aPos
= aSourceRange
.aStart
;
1005 OUString aValue
= static_cast<const ScChangeActionContent
*>(pSourceAction
)->GetNewString( m_pDocument
.get() );
1006 ScMatrixMode eMatrix
= ScMatrixMode::NONE
;
1007 const ScCellValue
& rCell
= static_cast<const ScChangeActionContent
*>(pSourceAction
)->GetNewCell();
1008 if (rCell
.getType() == CELLTYPE_FORMULA
)
1009 eMatrix
= rCell
.getFormula()->GetMatrixFlag();
1012 case ScMatrixMode::NONE
:
1013 pViewSh
->EnterData( aPos
.Col(), aPos
.Row(), aPos
.Tab(), aValue
);
1015 case ScMatrixMode::Formula
:
1019 rCell
.getFormula()->GetMatColsRows(nCols
, nRows
);
1020 aSourceRange
.aEnd
.SetCol( aPos
.Col() + nCols
- 1 );
1021 aSourceRange
.aEnd
.SetRow( aPos
.Row() + nRows
- 1 );
1022 aValue
= aValue
.copy(1, aValue
.getLength()-2); // remove the 1st and last characters.
1023 GetDocFunc().EnterMatrix( aSourceRange
,
1024 nullptr, nullptr, aValue
, false, false,
1025 OUString(), formula::FormulaGrammar::GRAM_DEFAULT
);
1028 case ScMatrixMode::Reference
: // do nothing
1033 case SC_CAT_INSERT_TABS
:
1036 m_pDocument
->CreateValidTabName( aName
);
1037 (void)GetDocFunc().InsertTable( aSourceRange
.aStart
.Tab(), aName
, true, false );
1040 case SC_CAT_INSERT_ROWS
:
1041 (void)GetDocFunc().InsertCells( aSourceRange
, nullptr, INS_INSROWS_BEFORE
, true, false );
1043 case SC_CAT_INSERT_COLS
:
1044 (void)GetDocFunc().InsertCells( aSourceRange
, nullptr, INS_INSCOLS_BEFORE
, true, false );
1046 case SC_CAT_DELETE_TABS
:
1047 (void)GetDocFunc().DeleteTable( aSourceRange
.aStart
.Tab(), true );
1049 case SC_CAT_DELETE_ROWS
:
1051 const ScChangeActionDel
* pDel
= static_cast<const ScChangeActionDel
*>(pSourceAction
);
1052 if ( pDel
->IsTopDelete() )
1054 aSourceRange
= pDel
->GetOverAllRange().MakeRange( GetDocument() );
1055 (void)GetDocFunc().DeleteCells( aSourceRange
, nullptr, DelCellCmd::Rows
, false );
1057 // #i101099# [Collaboration] Changes are not correctly shown
1060 ScChangeAction
* pAct
= pThisTrack
->GetLast();
1061 if ( pAct
&& pAct
->GetType() == eSourceType
&& pAct
->IsDeletedIn() && !pSourceAction
->IsDeletedIn() )
1063 pAct
->RemoveAllDeletedIn();
1069 case SC_CAT_DELETE_COLS
:
1071 const ScChangeActionDel
* pDel
= static_cast<const ScChangeActionDel
*>(pSourceAction
);
1072 if ( pDel
->IsTopDelete() && !pDel
->IsTabDeleteCol() )
1073 { // deleted table contains deleted cols, which are not
1074 aSourceRange
= pDel
->GetOverAllRange().MakeRange( GetDocument() );
1075 (void)GetDocFunc().DeleteCells( aSourceRange
, nullptr, DelCellCmd::Cols
, false );
1081 const ScChangeActionMove
* pMove
= static_cast<const ScChangeActionMove
*>(pSourceAction
);
1082 ScRange
aFromRange( pMove
->GetFromRange().MakeRange( GetDocument() ) );
1083 (void)GetDocFunc().MoveBlock( aFromRange
,
1084 aSourceRange
.aStart
, true, true, false, false );
1089 // added to avoid warnings
1093 const OUString
& rComment
= pSourceAction
->GetComment();
1094 if ( !rComment
.isEmpty() )
1096 ScChangeAction
* pAct
= pThisTrack
->GetLast();
1097 if ( pAct
&& pAct
->GetActionNumber() > nOldActionMax
)
1098 pAct
->SetComment( rComment
);
1100 OSL_FAIL( "MergeDocument: what to do with the comment?!?" );
1103 // adjust references
1104 pSourceTrack
->MergeOwn( const_cast<ScChangeAction
*>(pSourceAction
), nFirstNewNumber
, bShared
);
1106 // merge action state
1107 if ( bShared
&& !pSourceAction
->IsRejected() )
1109 ScChangeAction
* pAct
= pThisTrack
->GetLast();
1110 if ( pAct
&& pAct
->GetActionNumber() > nOldActionMax
)
1112 ScChangeTrack::MergeActionState( pAct
, pSourceAction
);
1117 if ( bShared
&& pMergeMap
)
1119 ScChangeAction
* pAct
= pThisTrack
->GetLast();
1120 if ( pAct
&& pAct
->GetActionNumber() > nOldActionMax
)
1122 sal_uLong nActionMax
= pAct
->GetActionNumber();
1123 sal_uLong nActionCount
= nActionMax
- nOldActionMax
;
1124 sal_uLong nAction
= nActionMax
- nActionCount
+ 1;
1125 sal_uLong nSourceAction
= pSourceAction
->GetActionNumber() - nActionCount
+ 1;
1126 while ( nAction
<= nActionMax
)
1130 (*pMergeMap
)[ nAction
++ ] = nSourceAction
++;
1134 (*pMergeMap
)[ nSourceAction
++ ] = nAction
++;
1140 aProgress
.SetStateCountDown( --nNewActionCount
);
1142 pSourceAction
= pSourceAction
->GetNext();
1145 rMarkData
= std::move(aOldMarkData
);
1146 pThisTrack
->SetUser(aOldUser
);
1147 pThisTrack
->SetUseFixDateTime( false );
1149 pSourceTrack
->Clear(); //! this one is bungled now
1152 PostPaintGridAll(); // Reject() doesn't paint itself
1157 bool ScDocShell::MergeSharedDocument( ScDocShell
* pSharedDocShell
)
1159 if ( !pSharedDocShell
)
1164 ScChangeTrack
* pThisTrack
= m_pDocument
->GetChangeTrack();
1170 ScDocument
& rSharedDoc
= pSharedDocShell
->GetDocument();
1171 ScChangeTrack
* pSharedTrack
= rSharedDoc
.GetChangeTrack();
1172 if ( !pSharedTrack
)
1177 // reset show changes
1178 ScChangeViewSettings aChangeViewSet
;
1179 aChangeViewSet
.SetShowChanges( false );
1180 m_pDocument
->SetChangeViewSettings( aChangeViewSet
);
1182 // find first merge action in this document
1183 bool bIgnore100Sec
= !pThisTrack
->IsTimeNanoSeconds() || !pSharedTrack
->IsTimeNanoSeconds();
1184 ScChangeAction
* pThisAction
= pThisTrack
->GetFirst();
1185 ScChangeAction
* pSharedAction
= pSharedTrack
->GetFirst();
1186 while ( lcl_Equal( pThisAction
, pSharedAction
, bIgnore100Sec
) )
1188 pThisAction
= pThisAction
->GetNext();
1189 pSharedAction
= pSharedAction
->GetNext();
1192 if ( pSharedAction
)
1196 // merge own changes into shared document
1197 sal_uLong nActStartShared
= pSharedAction
->GetActionNumber();
1198 sal_uLong nActEndShared
= pSharedTrack
->GetActionMax();
1199 std::optional
<ScDocument
> pTmpDoc(std::in_place
);
1200 for ( sal_Int32 nIndex
= 0; nIndex
< m_pDocument
->GetTableCount(); ++nIndex
)
1203 pTmpDoc
->CreateValidTabName( sTabName
);
1204 pTmpDoc
->InsertTab( SC_TAB_APPEND
, sTabName
);
1206 m_pDocument
->GetChangeTrack()->Clone( &*pTmpDoc
);
1207 ScChangeActionMergeMap aOwnInverseMergeMap
;
1208 pSharedDocShell
->MergeDocument( *pTmpDoc
, true, true, 0, &aOwnInverseMergeMap
, true );
1210 sal_uLong nActStartOwn
= nActEndShared
+ 1;
1211 sal_uLong nActEndOwn
= pSharedTrack
->GetActionMax();
1214 ScConflictsList aConflictsList
;
1215 ScConflictsFinder
aFinder( pSharedTrack
, nActStartShared
, nActEndShared
, nActStartOwn
, nActEndOwn
, aConflictsList
);
1216 if ( aFinder
.Find() )
1218 ScConflictsListHelper::TransformConflictsList( aConflictsList
, nullptr, &aOwnInverseMergeMap
);
1223 weld::Window
* pWin
= GetActiveDialogParent();
1224 ScConflictsDlg
aDlg(pWin
, GetViewData(), &rSharedDoc
, aConflictsList
);
1225 if (aDlg
.run() == RET_CANCEL
)
1227 std::unique_ptr
<weld::MessageDialog
> xQueryBox(Application::CreateMessageDialog(pWin
,
1228 VclMessageType::Question
, VclButtonsType::YesNo
,
1229 ScResId(STR_DOC_WILLNOTBESAVED
)));
1230 xQueryBox
->set_default_response(RET_YES
);
1231 if (xQueryBox
->run() == RET_YES
)
1243 // undo own changes in shared document
1244 pSharedTrack
->Undo( nActStartOwn
, nActEndOwn
);
1246 // clone change track for merging into own document
1248 for ( sal_Int32 nIndex
= 0; nIndex
< m_pDocument
->GetTableCount(); ++nIndex
)
1251 pTmpDoc
->CreateValidTabName( sTabName
);
1252 pTmpDoc
->InsertTab( SC_TAB_APPEND
, sTabName
);
1254 pThisTrack
->Clone( &*pTmpDoc
);
1256 // undo own changes since last save in own document
1257 sal_uLong nStartShared
= pThisAction
->GetActionNumber();
1258 ScChangeAction
* pAction
= pThisTrack
->GetLast();
1259 while ( pAction
&& pAction
->GetActionNumber() >= nStartShared
)
1261 pThisTrack
->Reject( pAction
, true );
1262 pAction
= pAction
->GetPrev();
1265 // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
1266 pThisTrack
->Undo( nStartShared
, pThisTrack
->GetActionMax(), true );
1268 // merge shared changes into own document
1269 ScChangeActionMergeMap aSharedMergeMap
;
1270 MergeDocument( rSharedDoc
, true, true, 0, &aSharedMergeMap
);
1271 sal_uLong nEndShared
= pThisTrack
->GetActionMax();
1273 // resolve conflicts for shared non-content actions
1274 if ( !aConflictsList
.empty() )
1276 ScConflictsListHelper::TransformConflictsList( aConflictsList
, &aSharedMergeMap
, nullptr );
1277 ScConflictsResolver
aResolver( pThisTrack
, aConflictsList
);
1278 pAction
= pThisTrack
->GetAction( nEndShared
);
1279 while ( pAction
&& pAction
->GetActionNumber() >= nStartShared
)
1281 aResolver
.HandleAction( pAction
, true /*bIsSharedAction*/,
1282 false /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1283 pAction
= pAction
->GetPrev();
1286 nEndShared
= pThisTrack
->GetActionMax();
1288 // only show changes from shared document
1289 aChangeViewSet
.SetShowChanges( true );
1290 aChangeViewSet
.SetShowAccepted( true );
1291 aChangeViewSet
.SetHasActionRange();
1292 aChangeViewSet
.SetTheActionRange( nStartShared
, nEndShared
);
1293 m_pDocument
->SetChangeViewSettings( aChangeViewSet
);
1295 // merge own changes back into own document
1296 sal_uLong nStartOwn
= nEndShared
+ 1;
1297 ScChangeActionMergeMap aOwnMergeMap
;
1298 MergeDocument( *pTmpDoc
, true, true, nEndShared
- nStartShared
+ 1, &aOwnMergeMap
);
1300 sal_uLong nEndOwn
= pThisTrack
->GetActionMax();
1302 // resolve conflicts for shared content actions and own actions
1303 if ( !aConflictsList
.empty() )
1305 ScConflictsListHelper::TransformConflictsList( aConflictsList
, nullptr, &aOwnMergeMap
);
1306 ScConflictsResolver
aResolver( pThisTrack
, aConflictsList
);
1307 pAction
= pThisTrack
->GetAction( nEndShared
);
1308 while ( pAction
&& pAction
->GetActionNumber() >= nStartShared
)
1310 aResolver
.HandleAction( pAction
, true /*bIsSharedAction*/,
1311 true /*bHandleContentAction*/, false /*bHandleNonContentAction*/ );
1312 pAction
= pAction
->GetPrev();
1315 pAction
= pThisTrack
->GetAction( nEndOwn
);
1316 while ( pAction
&& pAction
->GetActionNumber() >= nStartOwn
)
1318 aResolver
.HandleAction( pAction
, false /*bIsSharedAction*/,
1319 true /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1320 pAction
= pAction
->GetPrev();
1326 // merge shared changes into own document
1327 sal_uLong nStartShared
= pThisTrack
->GetActionMax() + 1;
1328 MergeDocument( rSharedDoc
, true, true );
1329 sal_uLong nEndShared
= pThisTrack
->GetActionMax();
1331 // only show changes from shared document
1332 aChangeViewSet
.SetShowChanges( true );
1333 aChangeViewSet
.SetShowAccepted( true );
1334 aChangeViewSet
.SetHasActionRange();
1335 aChangeViewSet
.SetTheActionRange( nStartShared
, nEndShared
);
1336 m_pDocument
->SetChangeViewSettings( aChangeViewSet
);
1343 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(GetActiveDialogParent(),
1344 VclMessageType::Info
, VclButtonsType::Ok
,
1345 ScResId(STR_DOC_UPDATED
)));
1349 return ( pThisAction
!= nullptr );
1352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */