LibreOffice Module sc (master)  1
docsh3.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
21 #include <com/sun/star/document/XDocumentProperties.hpp>
22 
23 #include <scitems.hxx>
24 #include <rangelst.hxx>
25 #include <editeng/flstitem.hxx>
26 #include <editeng/paperinf.hxx>
27 #include <editeng/sizeitem.hxx>
28 #include <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>
44 
45 #include <docsh.hxx>
46 #include "docshimp.hxx"
47 #include <scmod.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>
54 #include <hints.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>
63 #include <redcom.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>
71 #include <memory>
72 #include <formulaopt.hxx>
73 
74 #include <comphelper/lok.hxx>
75 #include <sfx2/lokhelper.hxx>
76 
77 // Redraw - Notifications
78 
79 void ScDocShell::PostEditView( ScEditEngineDefaulter* pEditEngine, const ScAddress& rCursorPos )
80 {
81 // Broadcast( ScEditViewHint( pEditEngine, rCursorPos ) );
82 
83  // Test: only active ViewShell
84 
86  if (pViewSh && pViewSh->GetViewData().GetDocShell() == this)
87  {
88  ScEditViewHint aHint( pEditEngine, rCursorPos );
89  pViewSh->Notify( *this, aHint );
90  }
91 }
92 
94 {
95  Broadcast( SfxHint( SfxHintId::ScDataChanged ) );
96  SfxGetpApp()->Broadcast(SfxHint( SfxHintId::ScAnyDataChanged )); // Navigator
97  m_pDocument->PrepareFormulaCalc();
99 }
100 
101 void ScDocShell::PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
102  SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, PaintPartFlags nPart,
103  sal_uInt16 nExtFlags )
104 {
105  ScRange aRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
106  PostPaint(aRange, nPart, nExtFlags);
107 }
108 
109 void ScDocShell::PostPaint( const ScRangeList& rRanges, PaintPartFlags nPart, sal_uInt16 nExtFlags )
110 {
111  ScRangeList aPaintRanges;
112  for (size_t i = 0, n = rRanges.size(); i < n; ++i)
113  {
114  const ScRange& rRange = rRanges[i];
115  SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
116  SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
117  SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
118 
119  if (!m_pDocument->ValidCol(nCol1)) nCol1 = m_pDocument->MaxCol();
120  if (!m_pDocument->ValidRow(nRow1)) nRow1 = m_pDocument->MaxRow();
121  if (!m_pDocument->ValidCol(nCol2)) nCol2 = m_pDocument->MaxCol();
122  if (!m_pDocument->ValidRow(nRow2)) nRow2 = m_pDocument->MaxRow();
123 
124  if ( m_pPaintLockData )
125  {
126  // #i54081# PaintPartFlags::Extras still has to be broadcast because it changes the
127  // current sheet if it's invalid. All other flags added to pPaintLockData.
128  PaintPartFlags nLockPart = nPart & ~PaintPartFlags::Extras;
129  if ( nLockPart != PaintPartFlags::NONE )
130  {
132  m_pPaintLockData->AddRange( ScRange( nCol1, nRow1, nTab1,
133  nCol2, nRow2, nTab2 ), nLockPart );
134  }
135 
136  nPart &= PaintPartFlags::Extras; // for broadcasting
137  if (nPart == PaintPartFlags::NONE)
138  continue;
139  }
140 
141  if (nExtFlags & SC_PF_LINES) // respect space for lines
142  {
144  if (nCol1>0) --nCol1;
145  if (nCol2<m_pDocument->MaxCol()) ++nCol2;
146  if (nRow1>0) --nRow1;
147  if (nRow2<m_pDocument->MaxRow()) ++nRow2;
148  }
149 
150  // expand for the merged ones
151  if (nExtFlags & SC_PF_TESTMERGE)
152  m_pDocument->ExtendMerge( nCol1, nRow1, nCol2, nRow2, nTab1 );
153 
154  if ( nCol1 != 0 || nCol2 != m_pDocument->MaxCol() )
155  {
156  // Extend to whole rows if SC_PF_WHOLEROWS is set, or rotated or non-left
157  // aligned cells are contained (see UpdatePaintExt).
158  // Special handling for RTL text (#i9731#) is unnecessary now with full
159  // support of right-aligned text.
160 
161  if ( ( nExtFlags & SC_PF_WHOLEROWS ) ||
162  m_pDocument->HasAttrib( nCol1,nRow1,nTab1,
164  {
165  nCol1 = 0;
166  nCol2 = m_pDocument->MaxCol();
167  }
168  }
169  aPaintRanges.push_back(ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
170  }
171 
172  Broadcast(ScPaintHint(aPaintRanges.Combine(), nPart));
173 
174  // LOK: we are supposed to update the row / columns headers (and actually
175  // the document size too - cell size affects that, obviously)
177  {
178  ScModelObj* pModel = comphelper::getFromUnoTunnel<ScModelObj>(this->GetModel());
180  }
181 }
182 
184 {
185  PostPaint( 0,0,0, m_pDocument->MaxCol(),m_pDocument->MaxRow(),MAXTAB, PaintPartFlags::Grid );
186 }
187 
188 void ScDocShell::PostPaintCell( SCCOL nCol, SCROW nRow, SCTAB nTab )
189 {
190  PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PaintPartFlags::Grid, SC_PF_TESTMERGE );
191 }
192 
194 {
195  PostPaintCell( rPos.Col(), rPos.Row(), rPos.Tab() );
196 }
197 
199 {
200  PostPaint( 0,0,0, m_pDocument->MaxCol(),m_pDocument->MaxRow(),MAXTAB, PaintPartFlags::Extras );
201 }
202 
203 void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, const ScRange& rRange )
204 {
205  if ( ( rExtFlags & SC_PF_LINES ) == 0 &&
207  {
208  // If the range contains lines, shadow or conditional formats,
209  // set SC_PF_LINES to include one extra cell in all directions.
210 
211  rExtFlags |= SC_PF_LINES;
212  }
213 
214  if ( ( rExtFlags & SC_PF_WHOLEROWS ) == 0 &&
215  ( rRange.aStart.Col() != 0 || rRange.aEnd.Col() != m_pDocument->MaxCol() ) &&
217  {
218  // If the range contains (logically) right- or center-aligned cells,
219  // or rotated cells, set SC_PF_WHOLEROWS to paint the whole rows.
220  // This test isn't needed after the cell changes, because it's also
221  // tested in PostPaint. UpdatePaintExt may later be changed to do this
222  // only if called before the changes.
223 
224  rExtFlags |= SC_PF_WHOLEROWS;
225  }
226 }
227 
228 void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
229  SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab )
230 {
231  UpdatePaintExt( rExtFlags, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ) );
232 }
233 
235 {
236  if ( !m_pPaintLockData )
237  m_pPaintLockData.reset( new ScPaintLockData );
238  m_pPaintLockData->IncLevel(bDoc);
239 }
240 
242 {
243  if ( m_pPaintLockData )
244  {
245  if ( m_pPaintLockData->GetLevel(bDoc) )
246  m_pPaintLockData->DecLevel(bDoc);
247  if (!m_pPaintLockData->GetLevel(!bDoc) && !m_pPaintLockData->GetLevel(bDoc))
248  {
249  // Execute Paint now
250 
251  // don't continue collecting
252  std::unique_ptr<ScPaintLockData> pPaint = std::move(m_pPaintLockData);
253 
254  ScRangeListRef xRangeList = pPaint->GetRangeList();
255  if ( xRangeList.is() )
256  {
257  PaintPartFlags nParts = pPaint->GetParts();
258  for ( size_t i = 0, nCount = xRangeList->size(); i < nCount; i++ )
259  {
261  ScRange const & rRange = (*xRangeList)[i];
262  PostPaint( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
263  rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(),
264  nParts );
265  }
266  }
267 
268  if ( pPaint->GetModified() )
270  }
271  }
272  else
273  {
274  OSL_FAIL("UnlockPaint without LockPaint");
275  }
276 }
277 
278 void ScDocShell::LockDocument_Impl(sal_uInt16 nNew)
279 {
280  if (!m_nDocumentLock)
281  {
282  ScDrawLayer* pDrawLayer = m_pDocument->GetDrawLayer();
283  if (pDrawLayer)
284  pDrawLayer->setLock(true);
285  }
286  m_nDocumentLock = nNew;
287 }
288 
289 void ScDocShell::UnlockDocument_Impl(sal_uInt16 nNew)
290 {
291  m_nDocumentLock = nNew;
292  if (!m_nDocumentLock)
293  {
294  ScDrawLayer* pDrawLayer = m_pDocument->GetDrawLayer();
295  if (pDrawLayer)
296  pDrawLayer->setLock(false);
297  }
298 }
299 
300 void ScDocShell::SetLockCount(sal_uInt16 nNew)
301 {
302  if (nNew) // set
303  {
304  if ( !m_pPaintLockData )
305  m_pPaintLockData.reset( new ScPaintLockData );
306  m_pPaintLockData->SetDocLevel(nNew-1);
307  LockDocument_Impl(nNew);
308  }
309  else if (m_pPaintLockData) // delete
310  {
311  m_pPaintLockData->SetDocLevel(0); // at unlock, execute immediately
312  UnlockPaint_Impl(true); // now
314  }
315 }
316 
318 {
319  LockPaint_Impl(false);
320 }
321 
323 {
324  UnlockPaint_Impl(false);
325 }
326 
328 {
329  LockPaint_Impl(true);
331 }
332 
334 {
335  if (m_nDocumentLock)
336  {
337  UnlockPaint_Impl(true);
339  }
340  else
341  {
342  OSL_FAIL("UnlockDocument without LockDocument");
343  }
344 }
345 
346 void ScDocShell::SetInplace( bool bInplace )
347 {
348  if (m_bIsInplace != bInplace)
349  {
350  m_bIsInplace = bInplace;
352  }
353 }
354 
356 {
357  if (m_bIsInplace)
358  {
359  m_nPrtToScreenFactor = 1.0; // otherwise it does not match the inactive display
360  return;
361  }
362 
363  bool bTextWysiwyg = SC_MOD()->GetInputOptions().GetTextWysiwyg();
364  if (bTextWysiwyg)
365  {
366  m_nPrtToScreenFactor = 1.0;
367  return;
368  }
369 
370  OUString aTestString(
371  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789");
372  tools::Long nPrinterWidth = 0;
373  const ScPatternAttr* pPattern = &m_pDocument->GetPool()->GetDefaultItem(ATTR_PATTERN);
374 
375  vcl::Font aDefFont;
376  OutputDevice* pRefDev = GetRefDevice();
377  MapMode aOldMode = pRefDev->GetMapMode();
378  vcl::Font aOldFont = pRefDev->GetFont();
379 
380  pRefDev->SetMapMode(MapMode(MapUnit::MapPixel));
381  pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, pRefDev); // font color doesn't matter here
382  pRefDev->SetFont(aDefFont);
383  nPrinterWidth = pRefDev->PixelToLogic(Size(pRefDev->GetTextWidth(aTestString), 0), MapMode(MapUnit::Map100thMM)).Width();
384  pRefDev->SetFont(aOldFont);
385  pRefDev->SetMapMode(aOldMode);
386 
388  pVirtWindow->SetMapMode(MapMode(MapUnit::MapPixel));
389  pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, pVirtWindow); // font color doesn't matter here
390  pVirtWindow->SetFont(aDefFont);
391  double nWindowWidth = pVirtWindow->GetTextWidth(aTestString) / ScGlobal::nScreenPPTX;
392  nWindowWidth = o3tl::convert(nWindowWidth, o3tl::Length::twip, o3tl::Length::mm100);
393 
394  if (nPrinterWidth && nWindowWidth)
395  m_nPrtToScreenFactor = nPrinterWidth / nWindowWidth;
396  else
397  {
398  OSL_FAIL("GetTextSize returns 0 ??");
399  m_nPrtToScreenFactor = 1.0;
400  }
401 }
402 
403 void ScDocShell::InitOptions(bool bForLoading) // called from InitNew and Load
404 {
405  // Settings from the SpellCheckCfg get into Doc- and ViewOptions
406 
407  LanguageType nDefLang, nCjkLang, nCtlLang;
408  bool bAutoSpell;
409  ScModule::GetSpellSettings( nDefLang, nCjkLang, nCtlLang, bAutoSpell );
410  ScModule* pScMod = SC_MOD();
411 
412  ScDocOptions aDocOpt = pScMod->GetDocOptions();
413  ScFormulaOptions aFormulaOpt = pScMod->GetFormulaOptions();
414  ScViewOptions aViewOpt = pScMod->GetViewOptions();
415  aDocOpt.SetAutoSpell( bAutoSpell );
416 
418  {
419  // two-digit year entry from Tools->Options->General
420  aDocOpt.SetYear2000(officecfg::Office::Common::DateFormat::TwoDigitYear::get());
421  }
422 
423  if (bForLoading)
424  {
425  // #i112123# No style:decimal-places attribute means automatic decimals, not the configured default,
426  // so it must not be taken from the global options.
427  // Calculation settings are handled separately in ScXMLBodyContext::EndElement.
429 
430  // fdo#78294 The default null-date if
431  // <table:null-date table:date-value='...' />
432  // is absent is 1899-12-30 regardless what the configuration is set to.
433  // Import filters may override this value.
434  aDocOpt.SetDate( 30, 12, 1899);
435  }
436 
437  m_pDocument->SetDocOptions( aDocOpt );
438  m_pDocument->SetViewOptions( aViewOpt );
439  SetFormulaOptions( aFormulaOpt, bForLoading );
440 
441  // print options are now set directly before the printing
442 
443  m_pDocument->SetLanguage( nDefLang, nCjkLang, nCtlLang );
444 }
445 
447 {
448  return m_pDocument->GetPrinter();
449 }
450 
451 SfxPrinter* ScDocShell::GetPrinter(bool bCreateIfNotExist)
452 {
453  return m_pDocument->GetPrinter(bCreateIfNotExist);
454 }
455 
457 {
458  // pImpl->pFontList = new FontList( GetPrinter(), Application::GetDefaultDevice() );
459  m_pImpl->pFontList.reset(new FontList(GetRefDevice(), nullptr));
460  SvxFontListItem aFontListItem( m_pImpl->pFontList.get(), SID_ATTR_CHAR_FONTLIST );
461  PutItem( aFontListItem );
462 
464 }
465 
467 {
468  return m_pDocument->GetRefDevice();
469 }
470 
471 sal_uInt16 ScDocShell::SetPrinter( VclPtr<SfxPrinter> const & pNewPrinter, SfxPrinterChangeFlags nDiffFlags )
472 {
473  SfxPrinter *pOld = m_pDocument->GetPrinter( false );
474  if ( pOld && pOld->IsPrinting() )
475  return SFX_PRINTERROR_BUSY;
476 
477  if (nDiffFlags & SfxPrinterChangeFlags::PRINTER)
478  {
479  if ( m_pDocument->GetPrinter() != pNewPrinter )
480  {
481  m_pDocument->SetPrinter( pNewPrinter );
482  m_pDocument->SetPrintOptions();
483 
484  // MT: Use UpdateFontList: Will use Printer fonts only if needed!
485  /*
486  delete pImpl->pFontList;
487  pImpl->pFontList = new FontList( pNewPrinter, Application::GetDefaultDevice() );
488  SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
489  PutItem( aFontListItem );
490 
491  CalcOutputFactor();
492  */
493  if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
494  UpdateFontList();
495 
496  ScModule* pScMod = SC_MOD();
497  SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this );
498  while (pFrame)
499  {
500  SfxViewShell* pSh = pFrame->GetViewShell();
501  if (ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(pSh))
502  {
503  ScInputHandler* pInputHdl = pScMod->GetInputHdl(pViewSh);
504  if (pInputHdl)
505  pInputHdl->UpdateRefDevice();
506  }
507  pFrame = SfxViewFrame::GetNext( *pFrame, this );
508  }
509  }
510  }
511  else if (nDiffFlags & SfxPrinterChangeFlags::JOBSETUP)
512  {
513  SfxPrinter* pOldPrinter = m_pDocument->GetPrinter();
514  if (pOldPrinter)
515  {
516  pOldPrinter->SetJobSetup( pNewPrinter->GetJobSetup() );
517 
518  // #i6706# Call SetPrinter with the old printer again, so the drawing layer
519  // RefDevice is set (calling ReformatAllTextObjects and rebuilding charts),
520  // because the JobSetup (printer device settings) may affect text layout.
521  m_pDocument->SetPrinter( pOldPrinter );
522  CalcOutputFactor(); // also with the new settings
523  }
524  }
525 
526  if (nDiffFlags & SfxPrinterChangeFlags::OPTIONS)
527  {
528  m_pDocument->SetPrintOptions();
529  }
530 
531  if (nDiffFlags & (SfxPrinterChangeFlags::CHG_ORIENTATION | SfxPrinterChangeFlags::CHG_SIZE))
532  {
533  OUString aStyle = m_pDocument->GetPageStyle( GetCurTab() );
534  ScStyleSheetPool* pStPl = m_pDocument->GetStyleSheetPool();
535  SfxStyleSheet* pStyleSheet = static_cast<SfxStyleSheet*>(pStPl->Find(aStyle, SfxStyleFamily::Page));
536  if (pStyleSheet)
537  {
538  SfxItemSet& rSet = pStyleSheet->GetItemSet();
539 
540  if (nDiffFlags & SfxPrinterChangeFlags::CHG_ORIENTATION)
541  {
542  const SvxPageItem& rOldItem = rSet.Get(ATTR_PAGE);
543  bool bWasLand = rOldItem.IsLandscape();
544  bool bNewLand = ( pNewPrinter->GetOrientation() == Orientation::Landscape );
545  if (bNewLand != bWasLand)
546  {
547  SvxPageItem aNewItem( rOldItem );
548  aNewItem.SetLandscape( bNewLand );
549  rSet.Put( aNewItem );
550 
551  // flip size
552  Size aOldSize = rSet.Get(ATTR_PAGE_SIZE).GetSize();
553  // coverity[swapped_arguments : FALSE] - this is in the correct order
554  Size aNewSize(aOldSize.Height(),aOldSize.Width());
555  SvxSizeItem aNewSItem(ATTR_PAGE_SIZE,aNewSize);
556  rSet.Put( aNewSItem );
557  }
558  }
559  if (nDiffFlags & SfxPrinterChangeFlags::CHG_SIZE)
560  {
561  SvxSizeItem aPaperSizeItem( ATTR_PAGE_SIZE, SvxPaperInfo::GetPaperSize(pNewPrinter) );
562  rSet.Put( aPaperSizeItem );
563  }
564  }
565  }
566 
567  PostPaint(0,0,0,m_pDocument->MaxCol(),m_pDocument->MaxRow(),MAXTAB,PaintPartFlags::All);
568 
569  return 0;
570 }
571 
573 {
575  if (!pTrack)
576  return nullptr;
577 
578  SCTAB nTab = rPos.Tab();
579 
580  const ScChangeAction* pFound = nullptr;
581  const ScChangeAction* pAction = pTrack->GetFirst();
582  while (pAction)
583  {
584  ScChangeActionType eType = pAction->GetType();
586  if ( pAction->IsVisible() && eType != SC_CAT_DELETE_TABS )
587  {
588  const ScBigRange& rBig = pAction->GetBigRange();
589  if ( rBig.aStart.Tab() == nTab )
590  {
591  ScRange aRange = rBig.MakeRange( GetDocument() );
592 
593  if ( eType == SC_CAT_DELETE_ROWS )
594  aRange.aEnd.SetRow( aRange.aStart.Row() );
595  else if ( eType == SC_CAT_DELETE_COLS )
596  aRange.aEnd.SetCol( aRange.aStart.Col() );
597 
598  if ( aRange.Contains( rPos ) )
599  {
600  pFound = pAction; // the last one wins
601  }
602  }
603  if ( pAction->GetType() == SC_CAT_MOVE )
604  {
605  ScRange aRange =
606  static_cast<const ScChangeActionMove*>(pAction)->
607  GetFromRange().MakeRange( GetDocument() );
608  if ( aRange.Contains( rPos ) )
609  {
610  pFound = pAction;
611  }
612  }
613  }
614  pAction = pAction->GetNext();
615  }
616 
617  return const_cast<ScChangeAction*>(pFound);
618 }
619 
620 void ScDocShell::SetChangeComment( ScChangeAction* pAction, const OUString& rComment )
621 {
622  if (!pAction)
623  return;
624 
625  pAction->SetComment( rComment );
628 
629  // Dialog-Notify
631  if (pTrack)
632  {
633  sal_uLong nNumber = pAction->GetActionNumber();
634  pTrack->NotifyModified( ScChangeTrackMsgType::Change, nNumber, nNumber );
635  }
636 }
637 
638 void ScDocShell::ExecuteChangeCommentDialog( ScChangeAction* pAction, weld::Window* pParent, bool bPrevNext)
639 {
640  if (!pAction) return; // without action is nothing...
641 
642  OUString aComment = pAction->GetComment();
643  OUString aAuthor = pAction->GetUser();
644 
645  DateTime aDT = pAction->GetDateTime();
646  OUString aDate = ScGlobal::getLocaleData().getDate( aDT ) + " " +
647  ScGlobal::getLocaleData().getTime( aDT, false );
648 
650 
651  aSet.Put( SvxPostItTextItem ( aComment, SID_ATTR_POSTIT_TEXT ) );
652  aSet.Put( SvxPostItAuthorItem( aAuthor, SID_ATTR_POSTIT_AUTHOR ) );
653  aSet.Put( SvxPostItDateItem ( aDate, SID_ATTR_POSTIT_DATE ) );
654 
655  std::unique_ptr<ScRedComDialog> pDlg(new ScRedComDialog( pParent, aSet,this,pAction,bPrevNext));
656 
657  pDlg->Execute();
658 }
659 
661 {
662  ScChangeTrack* pTrack = m_pDocument->GetChangeTrack();
663  if ( pTrack && pTrack->GetFirst() )
664  {
666  }
667 
668  m_pDocument->EndChangeTracking();
669  m_pDocument->StartChangeTracking();
670 
671  OUString aOldUser;
672  pTrack = m_pDocument->GetChangeTrack();
673  if ( pTrack )
674  {
675  aOldUser = pTrack->GetUser();
676 
677  // check if comparing to same document
678 
679  OUString aThisFile;
680  const SfxMedium* pThisMed = GetMedium();
681  if (pThisMed)
682  aThisFile = pThisMed->GetName();
683  OUString aOtherFile;
684  SfxObjectShell* pOtherSh = rOtherDoc.GetDocumentShell();
685  if (pOtherSh)
686  {
687  const SfxMedium* pOtherMed = pOtherSh->GetMedium();
688  if (pOtherMed)
689  aOtherFile = pOtherMed->GetName();
690  }
691  bool bSameDoc = ( aThisFile == aOtherFile && !aThisFile.isEmpty() );
692  if ( !bSameDoc )
693  {
694  // create change actions from comparing with the name of the user
695  // who last saved the document
696  // (only if comparing different documents)
697 
698  using namespace ::com::sun::star;
699  uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
700  GetModel(), uno::UNO_QUERY_THROW);
701  uno::Reference<document::XDocumentProperties> xDocProps(
702  xDPS->getDocumentProperties());
703  OSL_ENSURE(xDocProps.is(), "no DocumentProperties");
704  OUString aDocUser = xDocProps->getModifiedBy();
705 
706  if ( !aDocUser.isEmpty() )
707  pTrack->SetUser( aDocUser );
708  }
709  }
710 
711  m_pDocument->CompareDocument( rOtherDoc );
712 
713  pTrack = m_pDocument->GetChangeTrack();
714  if ( pTrack )
715  pTrack->SetUser( aOldUser );
716 
719 }
720 
721 // Merge (combine documents)
722 
723 static bool lcl_Equal( const ScChangeAction* pA, const ScChangeAction* pB, bool bIgnore100Sec )
724 {
725  return pA && pB &&
726  pA->GetActionNumber() == pB->GetActionNumber() &&
727  pA->GetType() == pB->GetType() &&
728  pA->GetUser() == pB->GetUser() &&
729  (bIgnore100Sec ?
731  pA->GetDateTimeUTC() == pB->GetDateTimeUTC());
732  // don't compare state if an old change has been accepted
733 }
734 
735 static bool lcl_FindAction( ScDocument& rDoc, const ScChangeAction* pAction, ScDocument& rSearchDoc, const ScChangeAction* pFirstSearchAction, const ScChangeAction* pLastSearchAction, bool bIgnore100Sec )
736 {
737  if ( !pAction || !pFirstSearchAction || !pLastSearchAction )
738  {
739  return false;
740  }
741 
742  sal_uLong nLastSearchAction = pLastSearchAction->GetActionNumber();
743  const ScChangeAction* pA = pFirstSearchAction;
744  while ( pA && pA->GetActionNumber() <= nLastSearchAction )
745  {
746  if ( pAction->GetType() == pA->GetType() &&
747  pAction->GetUser() == pA->GetUser() &&
748  (bIgnore100Sec ?
750  pAction->GetDateTimeUTC() == pA->GetDateTimeUTC() ) &&
751  pAction->GetBigRange() == pA->GetBigRange() )
752  {
753  OUString aActionDesc = pAction->GetDescription(rDoc, true);
754  OUString aADesc = pA->GetDescription(rSearchDoc, true);
755  if (aActionDesc == aADesc)
756  {
757  OSL_FAIL( "lcl_FindAction(): found equal action!" );
758  return true;
759  }
760  }
761  pA = pA->GetNext();
762  }
763 
764  return false;
765 }
766 
767 void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheckDuplicates, sal_uLong nOffset, ScChangeActionMergeMap* pMergeMap, bool bInverseMap )
768 {
769  ScTabViewShell* pViewSh = GetBestViewShell( false );
770  if (!pViewSh)
771  return;
772 
773  ScChangeTrack* pSourceTrack = rOtherDoc.GetChangeTrack();
774  if (!pSourceTrack)
775  return;
776 
777  ScChangeTrack* pThisTrack = m_pDocument->GetChangeTrack();
778  if ( !pThisTrack )
779  { // turn on
780  m_pDocument->StartChangeTracking();
781  pThisTrack = m_pDocument->GetChangeTrack();
782  OSL_ENSURE(pThisTrack,"ChangeTracking not enabled?");
783  if ( !bShared )
784  {
785  // turn on visual RedLining
786  ScChangeViewSettings aChangeViewSet;
787  aChangeViewSet.SetShowChanges(true);
788  m_pDocument->SetChangeViewSettings(aChangeViewSet);
789  }
790  }
791 
792  // include Nano seconds in compare?
793  bool bIgnore100Sec = !pSourceTrack->IsTimeNanoSeconds() ||
794  !pThisTrack->IsTimeNanoSeconds();
795 
796  // find common initial position
797  sal_uLong nFirstNewNumber = 0;
798  const ScChangeAction* pSourceAction = pSourceTrack->GetFirst();
799  const ScChangeAction* pThisAction = pThisTrack->GetFirst();
800  // skip identical actions
801  while ( lcl_Equal( pSourceAction, pThisAction, bIgnore100Sec ) )
802  {
803  nFirstNewNumber = pSourceAction->GetActionNumber() + 1;
804  pSourceAction = pSourceAction->GetNext();
805  pThisAction = pThisAction->GetNext();
806  }
807  // pSourceAction and pThisAction now point to the first "own" actions
808  // The common actions before don't interest at all
809 
811 
812  const ScChangeAction* pFirstMergeAction = pSourceAction;
813  const ScChangeAction* pFirstSearchAction = pThisAction;
814 
815  // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
816  const ScChangeAction* pLastSearchAction = pThisTrack->GetLast();
817 
818  // Create MergeChangeData from the following actions
819  sal_uLong nNewActionCount = 0;
820  const ScChangeAction* pCount = pSourceAction;
821  while ( pCount )
822  {
823  if ( bShared || !ScChangeTrack::MergeIgnore( *pCount, nFirstNewNumber ) )
824  ++nNewActionCount;
825  pCount = pCount->GetNext();
826  }
827  if (!nNewActionCount)
828  return;
829  // from here on no return
830 
831  ScProgress aProgress( this, "...", nNewActionCount, true );
832 
833  sal_uLong nLastMergeAction = pSourceTrack->GetLast()->GetActionNumber();
834  // UpdateReference-Undo, valid references for the last common state
835  pSourceTrack->MergePrepare( pFirstMergeAction, bShared );
836 
837  // adjust MergeChangeData to all yet following actions in this document
838  // -> references valid for this document
839  while ( pThisAction )
840  {
841  // #i87049# [Collaboration] Conflict between delete row and insert content is not merged correctly
842  if ( !bShared || !ScChangeTrack::MergeIgnore( *pThisAction, nFirstNewNumber ) )
843  {
844  ScChangeActionType eType = pThisAction->GetType();
845  switch ( eType )
846  {
847  case SC_CAT_INSERT_COLS :
848  case SC_CAT_INSERT_ROWS :
849  case SC_CAT_INSERT_TABS :
850  pSourceTrack->AppendInsert( pThisAction->GetBigRange().MakeRange( GetDocument() ) );
851  break;
852  case SC_CAT_DELETE_COLS :
853  case SC_CAT_DELETE_ROWS :
854  case SC_CAT_DELETE_TABS :
855  {
856  const ScChangeActionDel* pDel = static_cast<const ScChangeActionDel*>(pThisAction);
857  if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
858  { // deleted table contains deleted cols, which are not
859  sal_uLong nStart, nEnd;
860  pSourceTrack->AppendDeleteRange(
861  pDel->GetOverAllRange().MakeRange( GetDocument() ), nullptr, nStart, nEnd );
862  }
863  }
864  break;
865  case SC_CAT_MOVE :
866  {
867  const ScChangeActionMove* pMove = static_cast<const ScChangeActionMove*>(pThisAction);
868  pSourceTrack->AppendMove( pMove->GetFromRange().MakeRange( GetDocument() ),
869  pMove->GetBigRange().MakeRange( GetDocument() ), nullptr );
870  }
871  break;
872  default:
873  {
874  // added to avoid warnings
875  }
876  }
877  }
878  pThisAction = pThisAction->GetNext();
879  }
880 
881  LockPaint(); // #i73877# no repainting after each action
882 
883  // take over MergeChangeData into the current document
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 )
891  {
892  bool bMergeAction = false;
893  if ( bShared )
894  {
895  if ( !bCheckDuplicates || !lcl_FindAction( rOtherDoc, pSourceAction, *m_pDocument, pFirstSearchAction, pLastSearchAction, bIgnore100Sec ) )
896  {
897  bMergeAction = true;
898  }
899  }
900  else
901  {
902  if ( !ScChangeTrack::MergeIgnore( *pSourceAction, nFirstNewNumber ) )
903  {
904  bMergeAction = true;
905  }
906  }
907 
908  if ( bMergeAction )
909  {
910  ScChangeActionType eSourceType = pSourceAction->GetType();
911  if ( !bShared && pSourceAction->IsDeletedIn() )
912  {
915 
916  // lies in a range, which was deleted in this document
917  // -> is omitted
920 #if OSL_DEBUG_LEVEL > 0
921  OUString aValue;
922  if ( eSourceType == SC_CAT_CONTENT )
923  aValue = static_cast<const ScChangeActionContent*>(pSourceAction)->GetNewString( m_pDocument.get() );
924  SAL_WARN( "sc", aValue << " omitted");
925 #endif
926  }
927  else
928  {
930 
931  pThisTrack->SetUser( pSourceAction->GetUser() );
932  pThisTrack->SetFixDateTimeUTC( pSourceAction->GetDateTimeUTC() );
933  sal_uLong nOldActionMax = pThisTrack->GetActionMax();
934 
935  bool bExecute = true;
936  sal_uLong nReject = pSourceAction->GetRejectAction();
937  if ( nReject )
938  {
939  if ( bShared )
940  {
941  if ( nReject >= nFirstNewNumber )
942  {
943  nReject += nOffset;
944  }
945  ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
946  if ( pOldAction && pOldAction->IsVirgin() )
947  {
948  pThisTrack->Reject( pOldAction );
949  bHasRejected = true;
950  bExecute = false;
951  }
952  }
953  else
954  {
955  // decline old action (of the common ones)
956  ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
957  if (pOldAction && pOldAction->GetState() == SC_CAS_VIRGIN)
958  {
962 
963  pThisTrack->Reject(pOldAction);
964  bHasRejected = true; // for Paint
965  }
966  bExecute = false;
967  }
968  }
969 
970  if ( bExecute )
971  {
972  // execute normally
973  ScRange aSourceRange = pSourceAction->GetBigRange().MakeRange( GetDocument() );
974  rMarkData.SelectOneTable( aSourceRange.aStart.Tab() );
975  switch ( eSourceType )
976  {
977  case SC_CAT_CONTENT:
978  {
981 
982  OSL_ENSURE( aSourceRange.aStart == aSourceRange.aEnd, "huch?" );
983  ScAddress aPos = aSourceRange.aStart;
984  OUString aValue = static_cast<const ScChangeActionContent*>(pSourceAction)->GetNewString( m_pDocument.get() );
986  const ScCellValue& rCell = static_cast<const ScChangeActionContent*>(pSourceAction)->GetNewCell();
987  if (rCell.meType == CELLTYPE_FORMULA)
988  eMatrix = rCell.mpFormula->GetMatrixFlag();
989  switch ( eMatrix )
990  {
991  case ScMatrixMode::NONE :
992  pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
993  break;
994  case ScMatrixMode::Formula :
995  {
996  SCCOL nCols;
997  SCROW nRows;
998  rCell.mpFormula->GetMatColsRows(nCols, nRows);
999  aSourceRange.aEnd.SetCol( aPos.Col() + nCols - 1 );
1000  aSourceRange.aEnd.SetRow( aPos.Row() + nRows - 1 );
1001  aValue = aValue.copy(1, aValue.getLength()-2); // remove the 1st and last characters.
1002  GetDocFunc().EnterMatrix( aSourceRange,
1003  nullptr, nullptr, aValue, false, false,
1005  }
1006  break;
1007  case ScMatrixMode::Reference : // do nothing
1008  break;
1009  }
1010  }
1011  break;
1012  case SC_CAT_INSERT_TABS :
1013  {
1014  OUString aName;
1015  m_pDocument->CreateValidTabName( aName );
1016  (void)GetDocFunc().InsertTable( aSourceRange.aStart.Tab(), aName, true, false );
1017  }
1018  break;
1019  case SC_CAT_INSERT_ROWS:
1020  (void)GetDocFunc().InsertCells( aSourceRange, nullptr, INS_INSROWS_BEFORE, true, false );
1021  break;
1022  case SC_CAT_INSERT_COLS:
1023  (void)GetDocFunc().InsertCells( aSourceRange, nullptr, INS_INSCOLS_BEFORE, true, false );
1024  break;
1025  case SC_CAT_DELETE_TABS :
1026  (void)GetDocFunc().DeleteTable( aSourceRange.aStart.Tab(), true );
1027  break;
1028  case SC_CAT_DELETE_ROWS:
1029  {
1030  const ScChangeActionDel* pDel = static_cast<const ScChangeActionDel*>(pSourceAction);
1031  if ( pDel->IsTopDelete() )
1032  {
1033  aSourceRange = pDel->GetOverAllRange().MakeRange( GetDocument() );
1034  (void)GetDocFunc().DeleteCells( aSourceRange, nullptr, DelCellCmd::Rows, false );
1035 
1036  // #i101099# [Collaboration] Changes are not correctly shown
1037  if ( bShared )
1038  {
1039  ScChangeAction* pAct = pThisTrack->GetLast();
1040  if ( pAct && pAct->GetType() == eSourceType && pAct->IsDeletedIn() && !pSourceAction->IsDeletedIn() )
1041  {
1042  pAct->RemoveAllDeletedIn();
1043  }
1044  }
1045  }
1046  }
1047  break;
1048  case SC_CAT_DELETE_COLS:
1049  {
1050  const ScChangeActionDel* pDel = static_cast<const ScChangeActionDel*>(pSourceAction);
1051  if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
1052  { // deleted table contains deleted cols, which are not
1053  aSourceRange = pDel->GetOverAllRange().MakeRange( GetDocument() );
1054  (void)GetDocFunc().DeleteCells( aSourceRange, nullptr, DelCellCmd::Cols, false );
1055  }
1056  }
1057  break;
1058  case SC_CAT_MOVE :
1059  {
1060  const ScChangeActionMove* pMove = static_cast<const ScChangeActionMove*>(pSourceAction);
1061  ScRange aFromRange( pMove->GetFromRange().MakeRange( GetDocument() ) );
1062  (void)GetDocFunc().MoveBlock( aFromRange,
1063  aSourceRange.aStart, true, true, false, false );
1064  }
1065  break;
1066  default:
1067  {
1068  // added to avoid warnings
1069  }
1070  }
1071  }
1072  const OUString& rComment = pSourceAction->GetComment();
1073  if ( !rComment.isEmpty() )
1074  {
1075  ScChangeAction* pAct = pThisTrack->GetLast();
1076  if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1077  pAct->SetComment( rComment );
1078  else
1079  OSL_FAIL( "MergeDocument: what to do with the comment?!?" );
1080  }
1081 
1082  // adjust references
1083  pSourceTrack->MergeOwn( const_cast<ScChangeAction*>(pSourceAction), nFirstNewNumber, bShared );
1084 
1085  // merge action state
1086  if ( bShared && !pSourceAction->IsRejected() )
1087  {
1088  ScChangeAction* pAct = pThisTrack->GetLast();
1089  if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1090  {
1091  ScChangeTrack::MergeActionState( pAct, pSourceAction );
1092  }
1093  }
1094 
1095  // fill merge map
1096  if ( bShared && pMergeMap )
1097  {
1098  ScChangeAction* pAct = pThisTrack->GetLast();
1099  if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1100  {
1101  sal_uLong nActionMax = pAct->GetActionNumber();
1102  sal_uLong nActionCount = nActionMax - nOldActionMax;
1103  sal_uLong nAction = nActionMax - nActionCount + 1;
1104  sal_uLong nSourceAction = pSourceAction->GetActionNumber() - nActionCount + 1;
1105  while ( nAction <= nActionMax )
1106  {
1107  if ( bInverseMap )
1108  {
1109  (*pMergeMap)[ nAction++ ] = nSourceAction++;
1110  }
1111  else
1112  {
1113  (*pMergeMap)[ nSourceAction++ ] = nAction++;
1114  }
1115  }
1116  }
1117  }
1118  }
1119  aProgress.SetStateCountDown( --nNewActionCount );
1120  }
1121  pSourceAction = pSourceAction->GetNext();
1122  }
1123 
1124  rMarkData = std::move(aOldMarkData);
1125  pThisTrack->SetUser(aOldUser);
1126  pThisTrack->SetUseFixDateTime( false );
1127 
1128  pSourceTrack->Clear();
1129 
1130  if (bHasRejected)
1131  PostPaintGridAll(); // Reject() doesn't paint itself
1132 
1133  UnlockPaint();
1134 }
1135 
1137 {
1138  if ( !pSharedDocShell )
1139  {
1140  return false;
1141  }
1142 
1143  ScChangeTrack* pThisTrack = m_pDocument->GetChangeTrack();
1144  if ( !pThisTrack )
1145  {
1146  return false;
1147  }
1148 
1149  ScDocument& rSharedDoc = pSharedDocShell->GetDocument();
1150  ScChangeTrack* pSharedTrack = rSharedDoc.GetChangeTrack();
1151  if ( !pSharedTrack )
1152  {
1153  return false;
1154  }
1155 
1156  // reset show changes
1157  ScChangeViewSettings aChangeViewSet;
1158  aChangeViewSet.SetShowChanges( false );
1159  m_pDocument->SetChangeViewSettings( aChangeViewSet );
1160 
1161  // find first merge action in this document
1162  bool bIgnore100Sec = !pThisTrack->IsTimeNanoSeconds() || !pSharedTrack->IsTimeNanoSeconds();
1163  ScChangeAction* pThisAction = pThisTrack->GetFirst();
1164  ScChangeAction* pSharedAction = pSharedTrack->GetFirst();
1165  while ( lcl_Equal( pThisAction, pSharedAction, bIgnore100Sec ) )
1166  {
1167  pThisAction = pThisAction->GetNext();
1168  pSharedAction = pSharedAction->GetNext();
1169  }
1170 
1171  if ( pSharedAction )
1172  {
1173  if ( pThisAction )
1174  {
1175  // merge own changes into shared document
1176  sal_uLong nActStartShared = pSharedAction->GetActionNumber();
1177  sal_uLong nActEndShared = pSharedTrack->GetActionMax();
1178  std::optional<ScDocument> pTmpDoc(std::in_place);
1179  for ( sal_Int32 nIndex = 0; nIndex < m_pDocument->GetTableCount(); ++nIndex )
1180  {
1181  OUString sTabName;
1182  pTmpDoc->CreateValidTabName( sTabName );
1183  pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
1184  }
1185  m_pDocument->GetChangeTrack()->Clone( &*pTmpDoc );
1186  ScChangeActionMergeMap aOwnInverseMergeMap;
1187  pSharedDocShell->MergeDocument( *pTmpDoc, true, true, 0, &aOwnInverseMergeMap, true );
1188  pTmpDoc.reset();
1189  sal_uLong nActStartOwn = nActEndShared + 1;
1190  sal_uLong nActEndOwn = pSharedTrack->GetActionMax();
1191 
1192  // find conflicts
1193  ScConflictsList aConflictsList;
1194  ScConflictsFinder aFinder( pSharedTrack, nActStartShared, nActEndShared, nActStartOwn, nActEndOwn, aConflictsList );
1195  if ( aFinder.Find() )
1196  {
1197  ScConflictsListHelper::TransformConflictsList( aConflictsList, nullptr, &aOwnInverseMergeMap );
1198  bool bLoop = true;
1199  while ( bLoop )
1200  {
1201  bLoop = false;
1203  ScConflictsDlg aDlg(pWin, GetViewData(), &rSharedDoc, aConflictsList);
1204  if (aDlg.run() == RET_CANCEL)
1205  {
1206  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pWin,
1207  VclMessageType::Question, VclButtonsType::YesNo,
1208  ScResId(STR_DOC_WILLNOTBESAVED)));
1209  xQueryBox->set_default_response(RET_YES);
1210  if (xQueryBox->run() == RET_YES)
1211  {
1212  return false;
1213  }
1214  else
1215  {
1216  bLoop = true;
1217  }
1218  }
1219  }
1220  }
1221 
1222  // undo own changes in shared document
1223  pSharedTrack->Undo( nActStartOwn, nActEndOwn );
1224 
1225  // clone change track for merging into own document
1226  pTmpDoc.emplace();
1227  for ( sal_Int32 nIndex = 0; nIndex < m_pDocument->GetTableCount(); ++nIndex )
1228  {
1229  OUString sTabName;
1230  pTmpDoc->CreateValidTabName( sTabName );
1231  pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
1232  }
1233  pThisTrack->Clone( &*pTmpDoc );
1234 
1235  // undo own changes since last save in own document
1236  sal_uLong nStartShared = pThisAction->GetActionNumber();
1237  ScChangeAction* pAction = pThisTrack->GetLast();
1238  while ( pAction && pAction->GetActionNumber() >= nStartShared )
1239  {
1240  pThisTrack->Reject( pAction, true );
1241  pAction = pAction->GetPrev();
1242  }
1243 
1244  // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
1245  pThisTrack->Undo( nStartShared, pThisTrack->GetActionMax(), true );
1246 
1247  // merge shared changes into own document
1248  ScChangeActionMergeMap aSharedMergeMap;
1249  MergeDocument( rSharedDoc, true, true, 0, &aSharedMergeMap );
1250  sal_uLong nEndShared = pThisTrack->GetActionMax();
1251 
1252  // resolve conflicts for shared non-content actions
1253  if ( !aConflictsList.empty() )
1254  {
1255  ScConflictsListHelper::TransformConflictsList( aConflictsList, &aSharedMergeMap, nullptr );
1256  ScConflictsResolver aResolver( pThisTrack, aConflictsList );
1257  pAction = pThisTrack->GetAction( nEndShared );
1258  while ( pAction && pAction->GetActionNumber() >= nStartShared )
1259  {
1260  aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
1261  false /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1262  pAction = pAction->GetPrev();
1263  }
1264  }
1265  nEndShared = pThisTrack->GetActionMax();
1266 
1267  // only show changes from shared document
1268  aChangeViewSet.SetShowChanges( true );
1269  aChangeViewSet.SetShowAccepted( true );
1270  aChangeViewSet.SetHasActionRange();
1271  aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
1272  m_pDocument->SetChangeViewSettings( aChangeViewSet );
1273 
1274  // merge own changes back into own document
1275  sal_uLong nStartOwn = nEndShared + 1;
1276  ScChangeActionMergeMap aOwnMergeMap;
1277  MergeDocument( *pTmpDoc, true, true, nEndShared - nStartShared + 1, &aOwnMergeMap );
1278  pTmpDoc.reset();
1279  sal_uLong nEndOwn = pThisTrack->GetActionMax();
1280 
1281  // resolve conflicts for shared content actions and own actions
1282  if ( !aConflictsList.empty() )
1283  {
1284  ScConflictsListHelper::TransformConflictsList( aConflictsList, nullptr, &aOwnMergeMap );
1285  ScConflictsResolver aResolver( pThisTrack, aConflictsList );
1286  pAction = pThisTrack->GetAction( nEndShared );
1287  while ( pAction && pAction->GetActionNumber() >= nStartShared )
1288  {
1289  aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
1290  true /*bHandleContentAction*/, false /*bHandleNonContentAction*/ );
1291  pAction = pAction->GetPrev();
1292  }
1293 
1294  pAction = pThisTrack->GetAction( nEndOwn );
1295  while ( pAction && pAction->GetActionNumber() >= nStartOwn )
1296  {
1297  aResolver.HandleAction( pAction, false /*bIsSharedAction*/,
1298  true /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1299  pAction = pAction->GetPrev();
1300  }
1301  }
1302  }
1303  else
1304  {
1305  // merge shared changes into own document
1306  sal_uLong nStartShared = pThisTrack->GetActionMax() + 1;
1307  MergeDocument( rSharedDoc, true, true );
1308  sal_uLong nEndShared = pThisTrack->GetActionMax();
1309 
1310  // only show changes from shared document
1311  aChangeViewSet.SetShowChanges( true );
1312  aChangeViewSet.SetShowAccepted( true );
1313  aChangeViewSet.SetHasActionRange();
1314  aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
1315  m_pDocument->SetChangeViewSettings( aChangeViewSet );
1316  }
1317 
1318  // update view
1319  PostPaintExtras();
1320  PostPaintGridAll();
1321 
1322  std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetActiveDialogParent(),
1323  VclMessageType::Info, VclButtonsType::Ok,
1324  ScResId(STR_DOC_UPDATED)));
1325  xInfoBox->run();
1326  }
1327 
1328  return ( pThisAction != nullptr );
1329 }
1330 
1331 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScMarkData & GetMarkData()
Definition: viewdata.cxx:3135
bool IsLandscape() const
#define SC_PF_TESTMERGE
Definition: docsh.hxx:77
bool is() const
void UnlockPaint()
Definition: docsh3.cxx:322
sal_Int32 nIndex
CellType meType
Definition: cellvalue.hxx:37
ScAddress aStart
Definition: address.hxx:497
ScDocShell * GetDocShell() const
Definition: viewdata.hxx:354
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:42
ScChangeActionType GetType() const
Definition: chgtrack.hxx:317
SfxPrinter * GetPrinter(bool bCreateIfNotExist=true)
Definition: docsh3.cxx:451
constexpr TypedWhichId< SvxSizeItem > ATTR_PAGE_SIZE(161)
constexpr TypedWhichId< ScPatternAttr > ATTR_PATTERN(156)
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
void RemoveAllDeletedIn()
Definition: chgtrack.cxx:333
void PostEditView(ScEditEngineDefaulter *pEditEngine, const ScAddress &rCursorPos)
Definition: docsh3.cxx:79
std::unordered_map< sal_uLong, sal_uLong > ScChangeActionMergeMap
Definition: docsh.hxx:65
SCROW Row() const
Definition: address.hxx:274
void PostPaintGridAll()
Definition: docsh3.cxx:183
const OUString & GetUser() const
Definition: chgtrack.hxx:972
ScChangeAction * GetNext() const
Definition: chgtrack.hxx:322
static void GetSpellSettings(LanguageType &rDefLang, LanguageType &rCjkLang, LanguageType &rCtlLang, bool &rAutoSpell)
Definition: scmod.cxx:2254
static weld::Window * GetActiveDialogParent()
Definition: docsh.cxx:3089
ScChangeAction * GetLast() const
Definition: chgtrack.hxx:954
double m_nPrtToScreenFactor
Definition: docsh.hxx:86
void PostPaintCell(SCCOL nCol, SCROW nRow, SCTAB nTab)
Definition: docsh3.cxx:188
SC_DLLPUBLIC ScChangeAction * GetAction(sal_uLong nAction) const
Definition: chgtrack.cxx:2115
ScChangeActionState GetState() const
Definition: chgtrack.hxx:318
const OUString & GetName() const
sal_uIntPtr sal_uLong
virtual Printer * GetDocumentPrinter() override
Definition: docsh3.cxx:446
long Long
bool IsDeletedIn() const
Definition: chgtrack.cxx:316
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
SAL_DLLPRIVATE void UnlockDocument_Impl(sal_uInt16 nNew)
Definition: docsh3.cxx:289
void SetLandscape(bool bL)
sal_Int64 n
css::uno::Reference< css::frame::XModel3 > GetModel() const
bool IsVirgin() const
Definition: chgtrack.cxx:121
void SetComment(const OUString &rStr)
Definition: chgtrack.cxx:535
void SetDocumentModified()
Definition: docsh.cxx:2959
void PostPaintExtras()
Definition: docsh3.cxx:198
const MapMode & GetMapMode() const
ScChangeActionType
Definition: chgtrack.hxx:62
bool DeleteTable(SCTAB nTab, bool bRecord)
Definition: docfunc.cxx:3321
void MergeDocument(ScDocument &rOtherDoc, bool bShared=false, bool bCheckDuplicates=false, sal_uLong nOffset=0, ScChangeActionMergeMap *pMergeMap=nullptr, bool bInverseMap=false)
Definition: docsh3.cxx:767
ScRange Combine() const
Definition: rangelst.cxx:1107
ScAddress aEnd
Definition: address.hxx:498
::std::vector< ScConflictsListEntry > ScConflictsList
virtual SfxItemSet & GetItemSet()
virtual OUString GetDescription(ScDocument &rDoc, bool bSplitRange=false, bool bWarning=true) const
Definition: chgtrack.cxx:419
sal_uLong GetActionMax() const
Definition: chgtrack.hxx:955
sal_Int64 Tab() const
Definition: bigrange.hxx:46
void PutItem(const SfxPoolItem &rItem)
bool IsTimeNanoSeconds() const
Definition: chgtrack.hxx:1133
SAL_DLLPRIVATE void InitOptions(bool bForLoading)
Definition: docsh3.cxx:403
RET_CANCEL
void SetMapMode()
bool InsertCells(const ScRange &rRange, const ScMarkData *pTabMark, InsCellCmd eCmd, bool bRecord, bool bApi, bool bPartOfPaste=false)
Definition: docfunc.cxx:1736
ScChangeAction * GetPrev() const
Definition: chgtrack.hxx:323
SfxApplication * SfxGetpApp()
static OutputDevice * GetDefaultDevice()
void SetFormulaOptions(const ScFormulaOptions &rOpt, bool bForLoading=false)
Definition: docsh6.cxx:419
constexpr tools::Long Width() const
Store arbitrary cell value of any kind.
Definition: cellvalue.hxx:35
static SC_DLLPUBLIC const LocaleDataWrapper & getLocaleData()
Definition: global.cxx:1015
RET_YES
SfxPrinterChangeFlags
#define SFX_PRINTERROR_BUSY
void UpdatePaintExt(sal_uInt16 &rExtFlags, SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab)
Definition: docsh3.cxx:228
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:42
const vcl::Font & GetFont() const
static bool IsFuzzing()
void HandleAction(ScChangeAction *pAction, bool bIsSharedAction, bool bHandleContentAction, bool bHandleNonContentAction)
ScBigRange & GetFromRange()
Definition: chgtrack.hxx:526
int nCount
void MergePrepare(const ScChangeAction *pFirstMerge, bool bShared)
may only be used in a temporary opened document.
Definition: chgtrack.cxx:3137
SC_DLLPUBLIC void AppendMove(const ScRange &rFromRange, const ScRange &rToRange, ScDocument *pRefDoc)
Definition: chgtrack.cxx:2525
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: tabvwsh5.cxx:42
std::unique_ptr< ScPaintLockData > m_pPaintLockData
Definition: docsh.hxx:105
void SetFixDateTimeUTC(const DateTime &rDT)
Definition: chgtrack.hxx:984
void push_back(const ScRange &rRange)
Definition: rangelst.cxx:1137
ScChangeAction * GetFirst() const
Definition: chgtrack.hxx:953
void LockDocument()
Definition: docsh3.cxx:327
SCTAB Tab() const
Definition: address.hxx:283
void SetRow(SCROW nRowP)
Definition: address.hxx:287
SC_DLLPUBLIC void SetUser(const OUString &rUser)
Definition: chgtrack.cxx:2181
bool DeleteCells(const ScRange &rRange, const ScMarkData *pTabMark, DelCellCmd eCmd, bool bApi)
Definition: docfunc.cxx:2271
SC_DLLPUBLIC const ScDocOptions & GetDocOptions()
Definition: scmod.cxx:721
void SetTheActionRange(sal_uLong nFirst, sal_uLong nLast)
Definition: chgviset.hxx:126
sal_uInt16 SetPrinter(VclPtr< SfxPrinter > const &pNewPrinter, SfxPrinterChangeFlags nDiffFlags=SFX_PRINTER_ALL)
Definition: docsh3.cxx:471
void SetCol(SCCOL nColP)
Definition: address.hxx:291
ScViewData & GetViewData()
Definition: tabview.hxx:333
ScChangeTrack * GetChangeTrack() const
Definition: document.hxx:2485
SC_DLLPUBLIC void Undo(sal_uLong nStartAction, sal_uLong nEndAction, bool bMerge=false)
Definition: chgtrack.cxx:3034
bool IsTopDelete() const
Definition: chgtrack.cxx:813
SfxItemPool & GetPool() const
DocumentType eType
static void TransformConflictsList(ScConflictsList &rConflictsList, ScChangeActionMergeMap *pSharedMap, ScChangeActionMergeMap *pOwnMap)
void ExecuteChangeCommentDialog(ScChangeAction *pAction, weld::Window *pParent, bool bPrevNext=true)
Definition: docsh3.cxx:638
void NotifyModified(ScChangeTrackMsgType eMsgType, sal_uLong nStartAction, sal_uLong nEndAction)
Definition: chgtrack.cxx:2240
void CalcOutputFactor()
Definition: docsh3.cxx:355
static void GetFont(vcl::Font &rFont, const SfxItemSet &rItemSet, ScAutoFontColorMode eAutoMode, const OutputDevice *pOutDev=nullptr, const Fraction *pScale=nullptr, const SfxItemSet *pCondSet=nullptr, SvtScriptType nScript=SvtScriptType::NONE, const Color *pBackConfigColor=nullptr, const Color *pTextConfigColor=nullptr)
Static helper function to fill a font object from the passed item set.
Definition: patattr.cxx:251
const SCTAB SC_TAB_APPEND
Definition: address.hxx:90
int i
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
const DateTime & GetDateTimeUTC() const
Definition: chgtrack.hxx:315
SAL_DLLPRIVATE void LockDocument_Impl(sal_uInt16 nNew)
Definition: docsh3.cxx:278
sal_Int16 SCCOL
Definition: types.hxx:21
SAL_DLLPRIVATE void LockPaint_Impl(bool bDoc)
Definition: docsh3.cxx:234
bool IsTabDeleteCol() const
Definition: chgtrack.cxx:833
SC_DLLPUBLIC const ScFormulaOptions & GetFormulaOptions()
Definition: scmod.cxx:806
sal_uInt16 m_nDocumentLock
Definition: docsh.hxx:99
#define SC_MOD()
Definition: scmod.hxx:249
const OUString & GetComment() const
Definition: chgtrack.hxx:350
SC_DLLPUBLIC bool InsertTable(SCTAB nTab, const OUString &rName, bool bRecord, bool bApi)
Definition: docfunc.cxx:3269
ScChangeAction * GetChangeAction(const ScAddress &rPos)
Definition: docsh3.cxx:572
void SetDate(sal_uInt16 nD, sal_uInt16 nM, sal_Int16 nY)
Definition: docoptio.hxx:68
static SfxViewFrame * GetNext(const SfxViewFrame &rPrev, const SfxObjectShell *pDoc=nullptr, bool bOnlyVisible=true)
size_t size() const
Definition: rangelst.hxx:89
void SelectOneTable(SCTAB nTab)
Definition: markdata.cxx:174
SAL_DLLPRIVATE void UnlockPaint_Impl(bool bDoc)
Definition: docsh3.cxx:241
void SetYear2000(sal_uInt16 nVal)
Definition: docoptio.hxx:84
static bool MergeIgnore(const ScChangeAction &, sal_uLong nFirstMerge)
Definition: chgtrack.cxx:3126
void UnlockDocument()
Definition: docsh3.cxx:333
ScBigRange & GetBigRange()
Definition: chgtrack.hxx:231
ScBigRange GetOverAllRange() const
Definition: chgtrack.cxx:889
std::shared_ptr< ScDocument > m_pDocument
Definition: docsh.hxx:82
static Size GetPaperSize(Paper ePaper, MapUnit eUnit=MapUnit::MapTwip)
SC_DLLPUBLIC void AppendDeleteRange(const ScRange &, ScDocument *pRefDoc, SCTAB nDz, sal_uLong nRejectingInsert)
Definition: chgtrack.cxx:2389
void SetStateCountDown(sal_uInt64 nVal)
Definition: progress.hxx:88
const SCTAB MAXTAB
Definition: address.hxx:70
static ScViewData * GetViewData()
Definition: docsh4.cxx:2592
void PostPaint(SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, PaintPartFlags nPart, sal_uInt16 nExtFlags=0)
Definition: docsh3.cxx:101
void PostDataChanged()
Definition: docsh3.cxx:93
SfxViewShell * GetViewShell() const
SCCOL Col() const
Definition: address.hxx:279
bool IsRejected() const
Definition: chgtrack.cxx:131
void SetChangeComment(ScChangeAction *pAction, const OUString &rComment)
Definition: docsh3.cxx:620
sal_uLong GetActionNumber() const
Definition: chgtrack.hxx:319
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
static const sal_uInt16 UNLIMITED_PRECISION
void SetStdPrecision(sal_uInt16 n)
Definition: docoptio.hxx:79
OUString getDate(const Date &rDate) const
void setLock(bool bLock)
void SetShowAccepted(bool bVal)
Definition: chgviset.hxx:113
void SetLockCount(sal_uInt16 nNew)
Definition: docsh3.cxx:300
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
sal_Int32 SCROW
Definition: types.hxx:17
void MergeOwn(ScChangeAction *pAct, sal_uLong nFirstMerge, bool bShared)
Definition: chgtrack.cxx:3169
ScBigAddress aStart
Definition: bigrange.hxx:108
#define SC_PF_LINES
Definition: docsh.hxx:76
static void notifyDocumentSizeChangedAllViews(vcl::ITiledRenderable *pDoc, bool bInvalidateAll=true)
static ScTabViewShell * GetActiveViewShell()
Definition: tabvwsh4.cxx:1075
bool IsEqualIgnoreNanoSec(const DateTime &rDateTime) const
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
constexpr tools::Long Height() const
bool Reject(ScChangeAction *, ScChangeActionMap *, bool bRecursion)
Definition: chgtrack.cxx:4129
void SetFont(const vcl::Font &rNewFont)
void GetMatColsRows(SCCOL &nCols, SCROW &nRows) const
void CompareDocument(ScDocument &rOtherDoc)
Definition: docsh3.cxx:660
OUString aName
void SetInplace(bool bInplace)
Definition: docsh3.cxx:346
bool IsVisible() const
Definition: chgtrack.cxx:141
static void MergeActionState(ScChangeAction *pAct, const ScChangeAction *pOtherAct)
Definition: chgtrack.cxx:4612
SC_DLLPUBLIC bool EnterMatrix(const ScRange &rRange, const ScMarkData *pTabMark, const ScTokenArray *pTokenArray, const OUString &rString, bool bApi, bool bEnglish, const OUString &rFormulaNmsp, const formula::FormulaGrammar::Grammar)
Definition: docfunc.cxx:4316
virtual short run()
std::unique_ptr< DocShell_Impl > m_pImpl
Definition: docsh.hxx:87
bool Contains(const ScAddress &) const
is Address& fully in Range?
Definition: address.hxx:718
static SC_DLLPUBLIC double nScreenPPTX
Horizontal pixel per twips factor.
Definition: global.hxx:574
constexpr TypedWhichId< SvxPageItem > ATTR_PAGE(159)
const ScDocument & GetDocument() const
Definition: docsh.hxx:220
ScMatrixMode
const OUString & GetUser() const
Definition: chgtrack.hxx:349
#define SC_PF_WHOLEROWS
Definition: docsh.hxx:78
void UpdateFontList()
Definition: docsh3.cxx:456
ScRange MakeRange(const ScDocument &rDoc) const
Definition: bigrange.hxx:134
const ScViewOptions & GetViewOptions()
Definition: scmod.cxx:705
static SfxViewFrame * GetFirst(const SfxObjectShell *pDoc=nullptr, bool bOnlyVisible=true)
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1080
#define SAL_WARN(area, stream)
void UpdateRefDevice()
Definition: inputhdl.cxx:877
ScInputHandler * GetInputHdl(ScTabViewShell *pViewSh=nullptr, bool bUseRef=true)
Input-Handler.
Definition: scmod.cxx:1352
void SetUseFixDateTime(bool bVal)
Definition: chgtrack.hxx:981
ScDocFunc & GetDocFunc()
Definition: docsh.hxx:222
ScTabViewShell * GetBestViewShell(bool bOnlyVisible=true)
Definition: docsh4.cxx:2608
bool MoveBlock(const ScRange &rSource, const ScAddress &rDestPos, bool bCut, bool bRecord, bool bPaint, bool bApi)
Definition: docfunc.cxx:2852
bool m_bIsInplace
Definition: docsh.hxx:92
SC_DLLPUBLIC void AppendInsert(const ScRange &rRange, bool bEndOfList=false)
Definition: chgtrack.cxx:2753
SC_DLLPUBLIC ScChangeTrack * Clone(ScDocument *pDocument) const
Definition: chgtrack.cxx:4351
void SetAutoSpell(bool bVal)
Definition: docoptio.hxx:54
OUString getTime(const tools::Time &rTime, bool bSec=true, bool b100Sec=false) const
PaintPartFlags
Definition: global.hxx:108
static bool lcl_FindAction(ScDocument &rDoc, const ScChangeAction *pAction, ScDocument &rSearchDoc, const ScChangeAction *pFirstSearchAction, const ScChangeAction *pLastSearchAction, bool bIgnore100Sec)
Definition: docsh3.cxx:735
static bool lcl_Equal(const ScChangeAction *pA, const ScChangeAction *pB, bool bIgnore100Sec)
Definition: docsh3.cxx:723
ScMatrixMode GetMatrixFlag() const
virtual SfxStyleSheetBase * Find(const OUString &, SfxStyleFamily eFam, SfxStyleSearchBits n=SfxStyleSearchBits::All)
static SCTAB GetCurTab()
Definition: docsh4.cxx:2599
void LockPaint()
Definition: docsh3.cxx:317
SC_DLLPUBLIC DateTime GetDateTime() const
Definition: chgtrack.cxx:405
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
sal_uLong GetRejectAction() const
Definition: chgtrack.hxx:320
sal_Int16 SCTAB
Definition: types.hxx:22
void EnterData(SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString &rString, const EditTextObject *pData=nullptr)
Definition: viewfunc.cxx:364
OutputDevice * GetRefDevice()
Definition: docsh3.cxx:466
bool MergeSharedDocument(ScDocShell *pSharedDocShell)
Definition: docsh3.cxx:1136
bool m_bDetectedRangeSegmentation false
void SetShowChanges(bool bFlag)
Definition: chgviset.hxx:78
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo
SfxMedium * GetMedium() const