LibreOffice Module sw (master) 1
redlndlg.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 <redline.hxx>
21#include <tools/datetime.hxx>
22#include <tools/lineend.hxx>
23#include <svl/eitem.hxx>
24#include <sfx2/viewfrm.hxx>
25#include <sfx2/dispatch.hxx>
26#include <svx/ctredlin.hxx>
27#include <svx/postattr.hxx>
28#include <utility>
29#include <vcl/commandevent.hxx>
30#include <swtypes.hxx>
31#include <wrtsh.hxx>
32#include <view.hxx>
33#include <swmodule.hxx>
34#include <redlndlg.hxx>
35#include <swwait.hxx>
36#include <uitool.hxx>
37#include <o3tl/string_view.hxx>
38
39#include <cmdid.h>
40#include <strings.hrc>
41
42// -> #111827#
43#include <swundo.hxx>
44#include <SwRewriter.hxx>
45// <- #111827#
46
47#include <vector>
48#include <svx/svxdlg.hxx>
49#include <osl/diagnose.h>
50#include <bitmaps.hlst>
51
52#include <docsh.hxx>
53
55#include <usrpref.hxx>
56#include <memory>
57
59
61 sal_uInt16 nId,
62 SfxBindings* pBindings,
63 SfxChildWinInfo* pInfo)
64 : SwChildWinWrapper(_pParent, nId)
65{
66 auto xDlg = std::make_shared<SwModelessRedlineAcceptDlg>(pBindings, this, _pParent->GetFrameWeld());
67 SetController(xDlg);
68 xDlg->Initialize(pInfo);
69}
70
71// newly initialise dialog after document switch
73{
74 bool bRet = SwChildWinWrapper::ReInitDlg(pDocSh);
75 if (bRet) // update immediately, doc switch!
76 static_cast<SwModelessRedlineAcceptDlg*>(GetController().get())->Activate();
77
78 return bRet;
79}
80
82 SfxBindings* _pBindings, SwChildWinWrapper* pChild, weld::Window *pParent)
83 : SfxModelessDialogController(_pBindings, pChild, pParent,
84 "svx/ui/acceptrejectchangesdialog.ui", "AcceptRejectChangesDialog")
85 , m_xContentArea(m_xBuilder->weld_container("container"))
86 , m_pChildWin(pChild)
87{
88 m_xImplDlg.reset(new SwRedlineAcceptDlg(m_xDialog, m_xBuilder.get(), m_xContentArea.get()));
89}
90
92{
93 SwView *pView = ::GetActiveView();
94 if (!pView) // can happen when switching to another app, when a Listbox in dialog
95 return; // had the focus previously (actually THs Bug)
96
97 SwDocShell *pDocSh = pView->GetDocShell();
98
99 if (m_pChildWin->GetOldDocShell() != pDocSh)
100 { // doc-switch
101 SwWait aWait( *pDocSh, false );
102 SwWrtShell* pSh = pView->GetWrtShellPtr();
103 if (!pSh)
104 return;
105
106 m_pChildWin->SetOldDocShell(pDocSh); // avoid recursion (using modified-Hdl)
107
108 bool bMod = pSh->IsModified();
109 SfxBoolItem aShow(FN_REDLINE_SHOW, true);
111 FN_REDLINE_SHOW, SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
112 { &aShow });
113 if (!bMod)
114 pSh->ResetModified();
115 m_xImplDlg->Init();
117
118 return;
119 }
120
122 m_xImplDlg->Activate();
123}
124
126{
127 if (pInfo != nullptr)
128 m_xImplDlg->Initialize(pInfo->aExtraString);
129
131}
132
134{
136 m_xImplDlg->FillInfo(rInfo.aExtraString);
137}
138
140{
141}
142
143SwRedlineAcceptDlg::SwRedlineAcceptDlg(std::shared_ptr<weld::Window> xParent, weld::Builder *pBuilder,
144 weld::Container *pContentArea, bool bAutoFormat)
145 : m_xParentDlg(std::move(xParent))
146 , m_aSelectTimer("SwRedlineAcceptDlg m_aSelectTimer")
147 , m_sInserted(SwResId(STR_REDLINE_INSERTED))
148 , m_sDeleted(SwResId(STR_REDLINE_DELETED))
149 , m_sFormated(SwResId(STR_REDLINE_FORMATTED))
150 , m_sTableChgd(SwResId(STR_REDLINE_TABLECHG))
151 , m_sFormatCollSet(SwResId(STR_REDLINE_FMTCOLLSET))
152 , m_sAutoFormat(SwResId(STR_REDLINE_AUTOFMT))
153 , m_bOnlyFormatedRedlines(false)
154 , m_bRedlnAutoFormat(bAutoFormat)
155 , m_bInhibitActivate(false)
156 , m_bHasTrackedColumn(false)
157 , m_xTabPagesCTRL(new SvxAcceptChgCtr(pContentArea))
158 , m_xPopup(pBuilder->weld_menu("writermenu"))
159 , m_xSortMenu(pBuilder->weld_menu("writersortmenu"))
160{
161 m_pTPView = m_xTabPagesCTRL->GetViewPage();
162
165
171 //tdf#89227 default to disabled, and only enable if possible to accept/reject
172 m_pTPView->EnableAccept(false);
173 m_pTPView->EnableReject(false);
178
179 m_xTabPagesCTRL->GetFilterPage()->SetReadyHdl(LINK(this, SwRedlineAcceptDlg, FilterChangedHdl));
180
181 weld::ComboBox* pActLB = m_xTabPagesCTRL->GetFilterPage()->GetLbAction();
182 pActLB->append_text(m_sInserted);
183 pActLB->append_text(m_sDeleted);
184 pActLB->append_text(m_sFormated);
185 pActLB->append_text(m_sTableChgd);
186
188 {
190 pActLB->append_text(m_sAutoFormat);
192 m_pTPView->DisableUndo(); // no UNDO events yet
193 }
194
195 pActLB->set_active(0);
196
197 weld::TreeView& rTreeView = m_pTable->GetWidget();
198 rTreeView.set_selection_mode(SelectionMode::Multiple);
199
200 rTreeView.connect_changed(LINK(this, SwRedlineAcceptDlg, SelectHdl));
201 rTreeView.connect_popup_menu(LINK(this, SwRedlineAcceptDlg, CommandHdl));
202
203 // avoid multiple selection of the same texts:
206}
207
209{
210}
211
213{
214 std::optional<SwWait> oWait;
215 if (SwView *pView = GetActiveView())
216 oWait.emplace(*pView->GetDocShell(), false);
217 weld::TreeView& rTreeView = m_pTable->GetWidget();
219
220 rTreeView.freeze();
221 if (nStart)
222 RemoveParents(nStart, m_RedlineParents.size() - 1);
223 else
224 {
225 rTreeView.clear();
226 m_RedlinData.clear();
227 m_RedlineChildren.clear();
228 m_RedlineParents.erase(m_RedlineParents.begin() + nStart, m_RedlineParents.end());
229 }
230 rTreeView.thaw();
231
232 // insert parents
233 InsertParents(nStart);
234 InitAuthors();
235
236 // #i69618# this moves the list box to the right position, visually
237 std::unique_ptr<weld::TreeIter> xSelEntry(rTreeView.make_iterator());
238 if (rTreeView.get_selected(xSelEntry.get()))
239 rTreeView.scroll_to_row(*xSelEntry); //#i70937#, force the scroll
240}
241
243{
244 if (!m_xTabPagesCTRL)
245 return;
246
247 SwView *pView = ::GetActiveView();
248 if (!pView)
249 return;
250 SwWrtShell* pSh = pView->GetWrtShellPtr();
251
252 SvxTPFilter *pFilterPage = m_xTabPagesCTRL->GetFilterPage();
253
254 std::vector<OUString> aStrings;
255 OUString sOldAuthor(pFilterPage->GetSelectedAuthor());
256 pFilterPage->ClearAuthors();
257
259
261 bool bIsNotFormated = false;
262
263 // determine authors
264 for ( SwRedlineTable::size_type i = 0; i < nCount; i++)
265 {
266 const SwRangeRedline& rRedln = pSh->GetRedline(i);
267
268 if( m_bOnlyFormatedRedlines && RedlineType::Format != rRedln.GetType() )
270
271 aStrings.push_back(rRedln.GetAuthorString());
272
273 for (sal_uInt16 nStack = 1; nStack < rRedln.GetStackCount(); nStack++)
274 {
275 aStrings.push_back(rRedln.GetAuthorString(nStack));
276 }
277 }
278
279 std::sort(aStrings.begin(), aStrings.end());
280 aStrings.erase(std::unique(aStrings.begin(), aStrings.end()), aStrings.end());
281
282 for (auto const & i: aStrings)
283 pFilterPage->InsertAuthor(i);
284
285 if (pFilterPage->SelectAuthor(sOldAuthor) == -1 && !aStrings.empty())
286 pFilterPage->SelectAuthor(aStrings[0]);
287
288 weld::TreeView& rTreeView = m_pTable->GetWidget();
289 bool const bEnable = pSh && !pSh->GetDoc()->GetDocShell()->IsReadOnly()
290 && rTreeView.n_children() != 0
291 && !pSh->getIDocumentRedlineAccess().GetRedlinePassword().hasElements();
292 bool bSel = rTreeView.get_selected(nullptr);
293
294 rTreeView.selected_foreach([this, pSh, &bIsNotFormated](weld::TreeIter& rEntry){
295 // find the selected redline
296 // (fdo#57874: ignore, if the redline is already gone)
299 {
300 const SwRangeRedline& rRedln = pSh->GetRedline( nPos );
301
302 bIsNotFormated |= RedlineType::Format != rRedln.GetType();
303 }
304 return false;
305 });
306
307 m_pTPView->EnableAccept( bEnable && bSel );
308 m_pTPView->EnableReject( bEnable && bSel );
309 m_pTPView->EnableClearFormat( bEnable && !bIsNotFormated && bSel );
310 m_pTPView->EnableAcceptAll( bEnable );
311 m_pTPView->EnableRejectAll( bEnable );
314}
315
316OUString SwRedlineAcceptDlg::GetActionImage(const SwRangeRedline& rRedln, sal_uInt16 nStack,
317 bool bTableChanges, bool bRowChanges)
318{
319 switch (rRedln.GetType(nStack))
320 {
321 case RedlineType::Insert: return bTableChanges
322 ? bRowChanges
323 ? OUString(BMP_REDLINE_ROW_INSERTION)
324 : OUString(BMP_REDLINE_COL_INSERTION)
325 : rRedln.IsMoved()
326 ? OUString(BMP_REDLINE_MOVED_INSERTION)
327 : rRedln.IsAnnotation()
328 ? OUString(BMP_REDLINE_COMMENT_INSERTION)
329 : OUString(BMP_REDLINE_INSERTED);
330 case RedlineType::Delete: return bTableChanges
331 ? bRowChanges
332 ? OUString(BMP_REDLINE_ROW_DELETION)
333 : OUString(BMP_REDLINE_COL_DELETION)
334 : rRedln.IsMoved()
335 ? OUString(BMP_REDLINE_MOVED_DELETION)
336 : rRedln.IsAnnotation()
337 ? OUString(BMP_REDLINE_COMMENT_DELETION)
338 : OUString(BMP_REDLINE_DELETED);
339 case RedlineType::Format: return BMP_REDLINE_FORMATTED;
340 case RedlineType::ParagraphFormat: return BMP_REDLINE_FORMATTED;
341 case RedlineType::Table: return BMP_REDLINE_TABLECHG;
342 case RedlineType::FmtColl: return BMP_REDLINE_FMTCOLLSET;
343 default: break;
344 }
345
346 return OUString();
347}
348
349OUString SwRedlineAcceptDlg::GetActionText(const SwRangeRedline& rRedln, sal_uInt16 nStack)
350{
351 switch( rRedln.GetType(nStack) )
352 {
353 case RedlineType::Insert: return m_sInserted;
354 case RedlineType::Delete: return m_sDeleted;
355 case RedlineType::Format: return m_sFormated;
356 case RedlineType::ParagraphFormat: return m_sFormated;
357 case RedlineType::Table: return m_sTableChgd;
358 case RedlineType::FmtColl: return m_sFormatCollSet;
359 default:;//prevent warning
360 }
361
362 return OUString();
363}
364
365// newly initialise after activation
367{
368 // prevent update if flag is set (#102547#)
370 return;
371
372 SwView *pView = ::GetActiveView();
373 if (!pView) // can happen when switching to another app
374 {
375 m_pTPView->EnableAccept(false);
376 m_pTPView->EnableReject(false);
381 return; // had the focus previously
382 }
383
384 SwWait aWait( *pView->GetDocShell(), false );
385
386 if (pView->GetDocShell()->IsReadOnly())
387 {
388 m_pTPView->EnableAccept(false);
389 m_pTPView->EnableReject(false);
394 // note: enabling is done in InitAuthors below
395 }
396
398
399 // did something change?
400 SwWrtShell* pSh = pView->GetWrtShellPtr();
401 if (!pSh)
402 return;
403
405
406 // check the number of pointers
407 for ( SwRedlineTable::size_type i = 0; i < nCount; i++)
408 {
409 const SwRangeRedline& rRedln = pSh->GetRedline(i);
410
411 if (i >= m_RedlineParents.size())
412 {
413 // new entries have been appended
414 Init(i);
415 return;
416 }
417
418 SwRedlineDataParent *const pParent = m_RedlineParents[i].get();
419 if (&rRedln.GetRedlineData() != pParent->pData)
420 {
421 // Redline-Parents were inserted, changed or deleted
422 i = CalcDiff(i, false);
423 if (i == SwRedlineTable::npos)
424 return;
425 continue;
426 }
427
428 const SwRedlineData *pRedlineData = rRedln.GetRedlineData().Next();
429 const SwRedlineDataChild *pBackupData = pParent->pNext;
430
431 if (!pRedlineData && pBackupData)
432 {
433 // Redline-Children were deleted
434 i = CalcDiff(i, true);
435 if (i == SwRedlineTable::npos)
436 return;
437 continue;
438 }
439 else
440 {
441 while (pRedlineData)
442 {
443 if (pRedlineData != pBackupData->pChild)
444 {
445 // Redline-Children were inserted, changed or deleted
446 i = CalcDiff(i, true);
447 if (i == SwRedlineTable::npos)
448 return;
449 continue;
450 }
451 pBackupData = pBackupData->pNext;
452 pRedlineData = pRedlineData->Next();
453 }
454 }
455 }
456
457 if (nCount != m_RedlineParents.size())
458 {
459 // Redlines were deleted at the end
460 Init(nCount);
461 return;
462 }
463
464 // check comment
465 weld::TreeView& rTreeView = m_pTable->GetWidget();
466 bool bIsShowChangesInMargin = SW_MOD()->GetUsrPref(false)->IsShowChangesInMargin();
467 for (SwRedlineTable::size_type i = 0; i < nCount; i++)
468 {
469 const SwRangeRedline& rRedln = pSh->GetRedline(i);
470 SwRedlineDataParent *const pParent = m_RedlineParents[i].get();
471
472 if(rRedln.GetComment() != pParent->sComment)
473 {
474 bool bShowDeletedTextAsComment = bIsShowChangesInMargin &&
475 RedlineType::Delete == rRedln.GetType() && rRedln.GetComment().isEmpty();
476 const OUString sComment = bShowDeletedTextAsComment
477 ? const_cast<SwRangeRedline&>(rRedln).GetDescr()
478 : rRedln.GetComment();
479 if (pParent->xTLBParent)
480 {
481 // update only comment
482 rTreeView.set_text(*pParent->xTLBParent, sComment.replace('\n', ' '), 3);
483 }
484 pParent->sComment = sComment;
485 }
486 }
487
488 InitAuthors();
489}
490
492{
493 if (!nStart || m_bHasTrackedColumn)
494 {
495 Init();
497 }
498
499 weld::TreeView& rTreeView = m_pTable->GetWidget();
500 rTreeView.freeze();
501 SwView *pView = ::GetActiveView();
502 if (!pView)
504
505 SwWrtShell* pSh = pView->GetWrtShellPtr();
506 if (!pSh)
508
509 bool bHasRedlineAutoFormat = HasRedlineAutoFormat();
510 SwRedlineDataParent *const pParent = m_RedlineParents[nStart].get();
511 const SwRangeRedline& rRedln = pSh->GetRedline(nStart);
512
513 if (bChild) // should actually never happen, but just in case...
514 {
515 // throw away all entry's children and initialise newly
516 SwRedlineDataChild* pBackupData = const_cast<SwRedlineDataChild*>(pParent->pNext);
517 SwRedlineDataChild* pNext;
518
519 while (pBackupData)
520 {
521 pNext = const_cast<SwRedlineDataChild*>(pBackupData->pNext);
522 if (pBackupData->xTLBChild)
523 rTreeView.remove(*pBackupData->xTLBChild);
524
525 auto it = std::find_if(m_RedlineChildren.begin(), m_RedlineChildren.end(),
526 [&pBackupData](const std::unique_ptr<SwRedlineDataChild>& rChildPtr) { return rChildPtr.get() == pBackupData; });
527 if (it != m_RedlineChildren.end())
528 m_RedlineChildren.erase(it);
529
530 pBackupData = pNext;
531 }
532 pParent->pNext = nullptr;
533
534 // insert new children
535 InsertChildren(pParent, rRedln, bHasRedlineAutoFormat);
536
537 rTreeView.thaw();
538 return nStart;
539 }
540
541 // have entries been deleted?
542 const SwRedlineData *pRedlineData = &rRedln.GetRedlineData();
543 for (SwRedlineTable::size_type i = nStart + 1; i < m_RedlineParents.size(); i++)
544 {
545 if (m_RedlineParents[i]->pData == pRedlineData)
546 {
547 // remove entries from nStart to i-1
548 RemoveParents(nStart, i - 1);
549 rTreeView.thaw();
550 return nStart - 1;
551 }
552 }
553
554 // entries been inserted?
556 pRedlineData = m_RedlineParents[nStart]->pData;
557
558 for (SwRedlineTable::size_type i = nStart + 1; i < nCount; i++)
559 {
560 if (&pSh->GetRedline(i).GetRedlineData() == pRedlineData)
561 {
562 rTreeView.thaw();
563 // insert entries from nStart to i-1
564 InsertParents(nStart, i - 1);
565 return nStart - 1;
566 }
567 }
568
569 rTreeView.thaw();
570 Init(nStart); // adjust all entries until the end
572}
573
574void SwRedlineAcceptDlg::InsertChildren(SwRedlineDataParent *pParent, const SwRangeRedline& rRedln, bool bHasRedlineAutoFormat)
575{
576 SwRedlineDataChild *pLastRedlineChild = nullptr;
577 const SwRedlineData *pRedlineData = &rRedln.GetRedlineData();
578 bool bAutoFormatRedline = rRedln.IsAutoFormat();
579
580 weld::TreeView& rTreeView = m_pTable->GetWidget();
581
582 OUString sAction = GetActionText(rRedln);
583 bool bValidParent = m_sFilterAction.isEmpty() || m_sFilterAction == sAction;
584 bValidParent = bValidParent && m_pTable->IsValidEntry(rRedln.GetAuthorString(), rRedln.GetTimeStamp(), rRedln.GetComment());
585 if (bHasRedlineAutoFormat)
586 {
587
588 if (pParent->pData->GetSeqNo())
589 {
590 std::pair<SwRedlineDataParentSortArr::const_iterator,bool> const ret
591 = m_aUsedSeqNo.insert(pParent);
592 if (ret.second) // already there
593 {
594 if (pParent->xTLBParent)
595 {
596 rTreeView.set_text(*(*ret.first)->xTLBParent, m_sAutoFormat, 0);
597 rTreeView.remove(*pParent->xTLBParent);
598 pParent->xTLBParent.reset();
599 }
600 return;
601 }
602 }
603 bValidParent = bValidParent && bAutoFormatRedline;
604 }
605 bool bValidTree = bValidParent;
606
607 for (sal_uInt16 nStack = 1; nStack < rRedln.GetStackCount(); nStack++)
608 {
609 pRedlineData = pRedlineData->Next();
610
611 SwRedlineDataChild* pRedlineChild = new SwRedlineDataChild;
612 pRedlineChild->pChild = pRedlineData;
613 m_RedlineChildren.push_back(std::unique_ptr<SwRedlineDataChild>(pRedlineChild));
614
615 if ( pLastRedlineChild )
616 pLastRedlineChild->pNext = pRedlineChild;
617 else
618 pParent->pNext = pRedlineChild;
619
620 sAction = GetActionText(rRedln, nStack);
621 bool bValidChild = m_sFilterAction.isEmpty() || m_sFilterAction == sAction;
622 bValidChild = bValidChild && m_pTable->IsValidEntry(rRedln.GetAuthorString(nStack), rRedln.GetTimeStamp(nStack), rRedln.GetComment());
623 if (bHasRedlineAutoFormat)
624 bValidChild = bValidChild && bAutoFormatRedline;
625 bValidTree |= bValidChild;
626
627 if (bValidChild)
628 {
629 std::unique_ptr<RedlinData> pData(new RedlinData);
630 pData->pData = pRedlineChild;
631 pData->bDisabled = true;
632
633 OUString sImage(GetActionImage(rRedln, nStack));
634 OUString sAuthor = rRedln.GetAuthorString(nStack);
635 pData->aDateTime = rRedln.GetTimeStamp(nStack);
636 pData->eType = rRedln.GetType(nStack);
637 OUString sDateEntry = GetAppLangDateTimeString(pData->aDateTime);
638 OUString sComment = rRedln.GetComment(nStack);
639
640 std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator());
641 OUString sId(weld::toId(pData.get()));
642 rTreeView.insert(pParent->xTLBParent.get(), -1, nullptr, &sId, nullptr, nullptr,
643 false, xChild.get());
644 m_RedlinData.push_back(std::move(pData));
645
646 rTreeView.set_image(*xChild, sImage, -1);
647 rTreeView.set_text(*xChild, sAuthor, 1);
648 rTreeView.set_text(*xChild, sDateEntry, 2);
649 rTreeView.set_text(*xChild, sComment, 3);
650
651 pRedlineChild->xTLBChild = std::move(xChild);
652 if (!bValidParent)
653 rTreeView.expand_row(*pParent->xTLBParent);
654 }
655 else
656 pRedlineChild->xTLBChild.reset();
657
658 pLastRedlineChild = pRedlineChild;
659 }
660
661 if (pLastRedlineChild)
662 pLastRedlineChild->pNext = nullptr;
663
664 if (!bValidTree && pParent->xTLBParent)
665 {
666 rTreeView.remove(*pParent->xTLBParent);
667 pParent->xTLBParent.reset();
668 if (bHasRedlineAutoFormat)
669 m_aUsedSeqNo.erase(pParent);
670 }
671}
672
674{
675 SwView *pView = ::GetActiveView();
676 if (!pView)
677 return;
678
679 SwWrtShell* pSh = pView->GetWrtShellPtr();
680 if (!pSh)
681 return;
682
684
685 std::vector<const weld::TreeIter*> aLBoxArr;
686
687 weld::TreeView& rTreeView = m_pTable->GetWidget();
688
689 // because of Bug of TLB that ALWAYS calls the SelectHandler at Remove:
691
692 bool bChildrenRemoved = false;
693 rTreeView.thaw();
694 rTreeView.unselect_all();
695
696 // set the cursor after the last entry because otherwise performance problem in TLB.
697 // TLB would otherwise reset the cursor at every Remove (expensive)
699 weld::TreeIter *pCurEntry = nullptr;
700 while( ( pCurEntry == nullptr ) && ( nPos > 0 ) )
701 {
702 --nPos;
703 pCurEntry = m_RedlineParents[nPos]->xTLBParent.get();
704 }
705
706 if (pCurEntry)
707 rTreeView.set_cursor(*pCurEntry);
708
709 rTreeView.freeze();
710
711 for (SwRedlineTable::size_type i = nStart; i <= nEnd; i++)
712 {
713 if (!bChildrenRemoved && m_RedlineParents[i]->pNext)
714 {
715 SwRedlineDataChild * pChildPtr =
716 const_cast<SwRedlineDataChild*>(m_RedlineParents[i]->pNext);
717 auto it = std::find_if(m_RedlineChildren.begin(), m_RedlineChildren.end(),
718 [&pChildPtr](const std::unique_ptr<SwRedlineDataChild>& rChildPtr) { return rChildPtr.get() == pChildPtr; });
719 if (it != m_RedlineChildren.end())
720 {
721 sal_uInt16 nChildren = 0;
722 while (pChildPtr)
723 {
724 pChildPtr = const_cast<SwRedlineDataChild*>(pChildPtr->pNext);
725 nChildren++;
726 }
727
728 m_RedlineChildren.erase(it, it + nChildren);
729 bChildrenRemoved = true;
730 }
731 }
732 weld::TreeIter *const pEntry = m_RedlineParents[i]->xTLBParent.get();
733 if (pEntry)
734 aLBoxArr.push_back(pEntry);
735 }
736
737 std::sort(aLBoxArr.begin(), aLBoxArr.end(), [&rTreeView](const weld::TreeIter* a, const weld::TreeIter* b) {
738 return rTreeView.iter_compare(*a, *b) == -1;
739 });
740 // clear TLB from behind
741 for (auto it = aLBoxArr.rbegin(); it != aLBoxArr.rend(); ++it)
742 {
743 const weld::TreeIter* pIter = *it;
744 rTreeView.remove(*pIter);
745 }
746
747 rTreeView.thaw();
748 rTreeView.connect_changed(LINK(this, SwRedlineAcceptDlg, SelectHdl));
749 // unfortunately by Remove it was selected from the TLB always again ...
750 rTreeView.unselect_all();
751 rTreeView.freeze();
752
753 m_RedlineParents.erase(m_RedlineParents.begin() + nStart, m_RedlineParents.begin() + nEnd + 1);
754}
755
757{
758 SwView *pView = ::GetActiveView();
759 if (!pView)
760 return;
761
762 SwWrtShell* pSh = pView->GetWrtShellPtr();
763 if (!pSh)
764 return;
765
766 bool bHasRedlineAutoFormat = HasRedlineAutoFormat();
767
769 nEnd = std::min(nEnd, (nCount - 1)); // also treats nEnd=SwRedlineTable::npos (until the end)
770
771 // reset m_bHasTrackedColumn before searching tracked column again
772 if ( m_bHasTrackedColumn && nStart == 0 )
773 m_bHasTrackedColumn = false;
774
775 if (nEnd == SwRedlineTable::npos)
776 return; // no redlines in the document
777
778 weld::TreeView& rTreeView = m_pTable->GetWidget();
779
780 SwRedlineDataParent* pRedlineParent;
781 const SwRangeRedline* pCurrRedline;
782 if (!nStart && !rTreeView.get_selected(nullptr))
783 {
784 pCurrRedline = pSh->GetCurrRedline();
785 if( !pCurrRedline )
786 {
787 pSh->SwCursorShell::Push();
788 pCurrRedline = pSh->SelNextRedline();
789 if( nullptr == pCurrRedline )
790 pCurrRedline = pSh->SelPrevRedline();
791 pSh->SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
792 }
793 }
794 else
795 pCurrRedline = nullptr;
796
797 rTreeView.freeze();
798 if (m_pTable->IsSorted())
799 rTreeView.make_unsorted();
800
801 bool bIsShowChangesInMargin = SW_MOD()->GetUsrPref(false)->IsShowChangesInMargin();
802
803 // collect redlines of tracked table/row/column insertion/deletions under a single tree list
804 // item to accept/reject the table change with a single click on Accept/Reject
805 // Note: because update of the tree list depends on parent count, we don't modify
806 // m_RedlineParents, only store the 2nd and more redlines as children of the tree list
807 // item of the first redline
808
809 // count of items stored as children (to adjust parent position)
810 SwRedlineTable::size_type nSkipRedlines = 0;
811 // count of items of the actual table change stored as children =
812 // redlines of the change - 1 (first redline is associated to the parent tree list item)
813 SwRedlineTable::size_type nSkipRedline = 0;
814
815 // descriptor redline of the tracked table row/column
816 SwRedlineTable::size_type nRowChange = 0;
817
818 // first redlines of the tracked table rows/columns, base of the parent tree lists
819 // of the other SwRangeRedlines of the tracked table rows or columns
820 std::vector<SwRedlineTable::size_type> aTableParents;
821
822 // show all redlines as tree list items,
823 // redlines of a tracked table (row) insertion/deletion showed as children of a single parent
824 for (SwRedlineTable::size_type i = nStart; i <= nEnd; i++)
825 {
826 const SwRangeRedline& rRedln = pSh->GetRedline(i);
827 const SwRedlineData *pRedlineData = &rRedln.GetRedlineData();
828 // redline is a child associated to this table row/column change
830
831 pRedlineParent = new SwRedlineDataParent;
832 pRedlineParent->pData = pRedlineData;
833 pRedlineParent->pNext = nullptr;
834
835 // handle tracked table row changes
836 const SwTableBox* pTableBox;
837 const SwTableLine* pTableLine;
838 bool bChange = false;
839 bool bRowChange = false;
840 if ( // not recognized yet as tracked table row change
841 nullptr != ( pTableBox = pSh->GetRedline(i).Start()->GetNode().GetTableBox() ) &&
842 nullptr != ( pTableLine = pTableBox->GetUpper() ) &&
843 // it's a tracked row (or column change) based on the cached row data
844 ( RedlineType::None != pTableLine->GetRedlineType() ||
845 RedlineType::None != pTableBox->GetRedlineType() ) )
846 {
847 // start redline search from the start from the tracked row/column change
848 SwRedlineTable::size_type nStartPos =
849 nRowChange > nSkipRedline ? nRowChange - nSkipRedline : 0;
850 bChange = true;
851 bRowChange = RedlineType::None != pTableLine->GetRedlineType();
852 nRowChange = bRowChange
853 ? pTableLine->UpdateTextChangesOnly(nStartPos)
854 : pTableBox->GetRedline();
855 // redline is there in a tracked table change
856 if ( SwRedlineTable::npos != nRowChange )
857 {
858 // join the consecutive deleted/inserted rows/columns under a single treebox item,
859 // if they have the same redline data (equal type, author and time stamp)
860 for (size_t j = 0; j < aTableParents.size(); j++)
861 {
862 // note: CanCombine() allows a time frame to join the changes within a short
863 // time period: this avoid of falling apart of the tracked columns inserted
864 // by several clicks
865 if ( pSh->GetRedline(nRowChange).GetRedlineData()
866 .CanCombine(pSh->GetRedline(aTableParents[j]).GetRedlineData()) )
867 {
868 nSkipRedline++;
869 nTableParent = aTableParents[j];
870 break;
871 }
872
873 }
874
875 if ( SwRedlineTable::npos == nTableParent )
876 {
877 // table redline didn't fit in the stored ones, create new parent
878 aTableParents.push_back(i);
879 }
880
881 // it needs major tree update later because of tracked table columns
882 if ( !m_bHasTrackedColumn && !bRowChange )
883 {
884 m_bHasTrackedColumn = true;
885 }
886 }
887 else
888 {
889 // redline is not in a tracked table change
890 bChange = bRowChange = false;
891 }
892 }
893
894 // empty parent cache for the last table
895 if ( !pTableBox )
896 {
897 aTableParents.clear();
898 }
899
900 bool bShowDeletedTextAsComment = bIsShowChangesInMargin &&
901 RedlineType::Delete == rRedln.GetType() && rRedln.GetComment().isEmpty();
902 const OUString& sComment = bShowDeletedTextAsComment
903 ? const_cast<SwRangeRedline&>(rRedln).GetDescr()
904 : rRedln.GetComment();
905 pRedlineParent->sComment = sComment.replace('\n', ' ');
906 m_RedlineParents.insert(m_RedlineParents.begin() + i,
907 std::unique_ptr<SwRedlineDataParent>(pRedlineParent));
908
909 std::unique_ptr<RedlinData> pData(new RedlinData);
910 pData->pData = pRedlineParent;
911 pData->bDisabled = false;
912
913 // use descriptor SwRangeRedline of the changed row, if needed to show
914 // the correct redline type, author and time stamp of the tracked row change
915 const SwRangeRedline& rChangeRedln = pSh->GetRedline(bChange ? nRowChange : i);
916
917 OUString sImage = GetActionImage(rChangeRedln, 0, bChange && aTableParents.back() == i, bRowChange );
918 OUString sAuthor = rChangeRedln.GetAuthorString(0);
919 pData->aDateTime = rChangeRedln.GetTimeStamp(0);
920 pData->eType = rChangeRedln.GetType(0);
921 OUString sDateEntry = GetAppLangDateTimeString(pData->aDateTime);
922
923 OUString sId = weld::toId(pData.get());
924 std::unique_ptr<weld::TreeIter> xParent(rTreeView.make_iterator());
925
926 if ( !bChange || aTableParents.back() == i )
927 {
928 rTreeView.insert(nullptr, i - nSkipRedlines, nullptr, &sId, nullptr, nullptr, false, xParent.get());
929 // before this was a tracked table change with more than a single redline
930 if ( nSkipRedline > 0 )
931 {
932 nSkipRedlines += nSkipRedline;
933 nSkipRedline = 0;
934 }
935 }
936 else
937 {
938 // put 2nd or more redlines of deleted/inserted rows as children of their first redline
939 SwRedlineDataParent *const pParent = m_RedlineParents[nTableParent].get();
940 rTreeView.insert(pParent->xTLBParent.get(), -1, nullptr, &sId, nullptr, nullptr, false, xParent.get());
941 }
942
943 m_RedlinData.push_back(std::move(pData));
944
945 rTreeView.set_image(*xParent, sImage, -1);
946 rTreeView.set_text(*xParent, sAuthor, 1);
947 rTreeView.set_text(*xParent, sDateEntry, 2);
948 rTreeView.set_text(*xParent, sComment, 3);
949
950 if (pCurrRedline == &rRedln)
951 {
952 rTreeView.thaw();
953 rTreeView.set_cursor(*xParent);
954 rTreeView.select(*xParent);
955 rTreeView.scroll_to_row(*xParent);
956 rTreeView.freeze();
957 }
958
959 pRedlineParent->xTLBParent = std::move(xParent);
960
961 InsertChildren(pRedlineParent, rRedln, bHasRedlineAutoFormat);
962 }
963 rTreeView.thaw();
964 if (m_pTable->IsSorted())
965 rTreeView.make_sorted();
966}
967
968void SwRedlineAcceptDlg::CallAcceptReject( bool bSelect, bool bAccept )
969{
970 SwView *pView = ::GetActiveView();
971 if (!pView)
972 return;
973
974 SwWrtShell* pSh = pView->GetWrtShellPtr();
975 if (!pSh)
976 return;
977
978 int nPos = -1;
979
980 typedef std::vector<std::unique_ptr<weld::TreeIter>> ListBoxEntries_t;
981 ListBoxEntries_t aRedlines;
982
983 // don't activate
984 OSL_ENSURE( !m_bInhibitActivate,
985 "recursive call of CallAcceptReject?");
986 m_bInhibitActivate = true;
987
988 weld::TreeView& rTreeView = m_pTable->GetWidget();
989
990 auto lambda = [this, pSh, bSelect, bAccept, &rTreeView, &nPos, &aRedlines](weld::TreeIter& rEntry) {
991 if (!rTreeView.get_iter_depth(rEntry))
992 {
993 if (bSelect && nPos == -1)
994 nPos = rTreeView.get_iter_index_in_parent(rEntry);
995
996 RedlinData *pData = weld::fromId<RedlinData*>(rTreeView.get_id(rEntry));
997
998 bool bIsNotFormatted = true;
999
1000 // first remove only changes with insertion/deletion, if they exist
1001 // (format-only changes haven't had real rejection yet, only an
1002 // approximation: clear direct formatting, so try to warn
1003 // with the extended button label "Reject All/Clear formatting")
1004 if ( !bSelect && !bAccept && !m_bOnlyFormatedRedlines )
1005 {
1006 SwRedlineTable::size_type nPosition = GetRedlinePos(rEntry);
1007 const SwRangeRedline& rRedln = pSh->GetRedline(nPosition);
1008
1009 if( RedlineType::Format == rRedln.GetType() )
1010 bIsNotFormatted = false;
1011 }
1012
1013 if (!pData->bDisabled && bIsNotFormatted)
1014 aRedlines.emplace_back(rTreeView.make_iterator(&rEntry));
1015 }
1016 return false;
1017 };
1018
1019 // collect redlines-to-be-accepted/rejected in aRedlines vector
1020 if (bSelect)
1021 rTreeView.selected_foreach(lambda);
1022 else
1023 rTreeView.all_foreach(lambda);
1024
1026 if( !bAccept )
1027 FnAccRej = &SwEditShell::RejectRedline;
1028
1029 SwWait aWait( *pSh->GetView().GetDocShell(), true );
1030 pSh->StartAction();
1031
1032 bool bMoreRedlines( aRedlines.size() > 1 ||
1033 // single item with children, e.g. multiple redlines of a table or table row deletion/insertion
1034 ( aRedlines.size() == 1 && rTreeView.iter_n_children(*aRedlines[0]) > 0 ) );
1035
1036 // don't add extra Undo label to a single item only with redline stack (i.e. old changes
1037 // on the same text range, stored only in OOXML)
1038 if ( bMoreRedlines && aRedlines.size() == 1 )
1039 {
1040 std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator( &*aRedlines[0] ));
1041 RedlinData *pData = weld::fromId<RedlinData*>(rTreeView.get_id(*xChild));
1042 if ( pData->bDisabled )
1043 bMoreRedlines = false;
1044 }
1045
1046 if ( bMoreRedlines )
1047 {
1048 OUString aTmpStr;
1049 {
1050 SwRewriter aRewriter;
1051 aRewriter.AddRule(UndoArg1,
1052 OUString::number(aRedlines.size()));
1053 aTmpStr = aRewriter.Apply(SwResId(STR_N_REDLINES));
1054 }
1055
1056 SwRewriter aRewriter;
1057 aRewriter.AddRule(UndoArg1, aTmpStr);
1058
1060 &aRewriter);
1061 }
1062
1063 // accept/reject the redlines in aRedlines. The absolute
1064 // position may change during the process (e.g. when two redlines
1065 // are merged in result of another one being deleted), so the
1066 // position must be resolved late and checked before using it.
1067 // (cf #102547#)
1068 for (const auto& rRedLine : aRedlines)
1069 {
1070 SwRedlineTable::size_type nPosition = GetRedlinePos( *rRedLine );
1071 if( nPosition != SwRedlineTable::npos )
1072 (pSh->*FnAccRej)( nPosition );
1073
1074 // handle redlines of table rows, stored as children of the item associated
1075 // to the deleted/inserted table row(s)
1076 std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator( &*rRedLine ));
1077 if ( rTreeView.iter_children(*xChild) )
1078 {
1079 RedlinData *pData = weld::fromId<RedlinData*>(rTreeView.get_id(*xChild));
1080 // disabled for redline stack, but not for redlines of table rows
1081 if ( !pData->bDisabled )
1082 {
1083 do
1084 {
1085 nPosition = GetRedlinePos( *xChild );
1086 if( nPosition != SwRedlineTable::npos )
1087 (pSh->*FnAccRej)( nPosition );
1088 }
1089 while ( rTreeView.iter_next_sibling(*xChild) );
1090 }
1091 }
1092 }
1093
1094 if ( bMoreRedlines )
1095 {
1096 pSh->EndUndo();
1097 }
1098
1099 pSh->EndAction();
1100
1101 m_bInhibitActivate = false;
1102 Activate();
1103
1104 if (nPos != -1 && rTreeView.n_children())
1105 {
1106 if (nPos >= rTreeView.n_children())
1107 nPos = rTreeView.n_children() - 1;
1108 rTreeView.select(nPos);
1109 rTreeView.scroll_to_row(nPos);
1110 rTreeView.set_cursor(nPos);
1111 SelectHdl(rTreeView);
1112 }
1114}
1115
1117{
1118 SwView* pView = GetActiveView();
1119 if (!pView)
1120 return SwRedlineTable::npos;
1121
1122 SwWrtShell* pSh = pView->GetWrtShellPtr();
1123 if (!pSh)
1124 return SwRedlineTable::npos;
1125
1126 weld::TreeView& rTreeView = m_pTable->GetWidget();
1127 return pSh->FindRedlineOfData( *static_cast<SwRedlineDataParent*>(weld::fromId<RedlinData*>(
1128 rTreeView.get_id(rEntry))->pData)->pData );
1129}
1130
1132{
1133 CallAcceptReject( true, true );
1134}
1135
1137{
1138 CallAcceptReject( false, true );
1139}
1140
1142{
1143 CallAcceptReject( true, false );
1144}
1145
1147{
1148 CallAcceptReject( false, false );
1149}
1150
1152{
1153 if (SwView* pView = GetActiveView())
1154 {
1155 pView->GetViewFrame().GetDispatcher()->
1156 Execute(SID_UNDO, SfxCallMode::SYNCHRON);
1157 m_pTPView->EnableUndo(pView->GetSlotState(SID_UNDO) != nullptr);
1158 }
1159
1160 Activate();
1161}
1162
1164{
1165 SvxTPFilter *pFilterTP = m_xTabPagesCTRL->GetFilterPage();
1166
1167 if (pFilterTP->IsAction())
1168 m_sFilterAction = pFilterTP->GetLbAction()->get_active_text();
1169 else
1170 m_sFilterAction.clear();
1171
1172 Init();
1173}
1174
1176{
1177 m_aSelectTimer.Start();
1178}
1179
1181{
1182 m_aSelectTimer.Stop();
1183
1184 SwView* pView = GetActiveView();
1185 if (!pView)
1186 return;
1187
1188 SwWrtShell* pSh = pView->GetWrtShellPtr();
1189 if (!pSh)
1190 return;
1191
1192 bool bIsNotFormated = false;
1193 bool bSel = false;
1194
1195 //#98883# don't select redlines while the dialog is not focused
1196 //#107938# But not only ask pTable if it has the focus. To move
1197 // the selection to the selected redline any child of pParentDlg
1198 // may the focus.
1199 if (!m_xParentDlg || m_xParentDlg->has_toplevel_focus())
1200 {
1201 weld::TreeView& rTreeView = m_pTable->GetWidget();
1202 std::unique_ptr<weld::TreeIter> xActEntry(rTreeView.make_iterator());
1203 if (rTreeView.get_selected(xActEntry.get()))
1204 {
1205 pSh->StartAction();
1206 pSh->EnterStdMode();
1207 SwViewShell::SetCareDialog(m_xParentDlg);
1208
1209 rTreeView.selected_foreach([this, pSh, &rTreeView, &xActEntry, &bIsNotFormated, &bSel](weld::TreeIter& rEntry){
1210 rTreeView.copy_iterator(rEntry, *xActEntry);
1211 if (rTreeView.get_iter_depth(rEntry))
1212 {
1213 rTreeView.iter_parent(*xActEntry);
1214 if (rTreeView.is_selected(*xActEntry))
1215 return false; // don't select twice
1216 }
1217 else
1218 bSel = true;
1219
1220 // #98864# find the selected redline (ignore, if the redline is already gone)
1221 SwRedlineTable::size_type nPos = GetRedlinePos(*xActEntry);
1223 {
1224
1225 const SwRangeRedline& rRedln = pSh->GetRedline( nPos );
1226 bIsNotFormated |= RedlineType::Format != rRedln.GetType();
1227
1228 if (pSh->GotoRedline(nPos, true))
1229 {
1230 pSh->SetInSelect();
1231 pSh->EnterAddMode();
1232 }
1233 }
1234
1235 // select all redlines of tracked table rows
1236 std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator( &*xActEntry ));
1237 if ( rTreeView.iter_children(*xChild) )
1238 {
1239 RedlinData *pData = reinterpret_cast<RedlinData*>(rTreeView.get_id(*xChild).toInt64());
1240 // disabled for redline stack, but not for redlines of table rows
1241 if ( !pData->bDisabled )
1242 {
1243 do
1244 {
1245 nPos = GetRedlinePos(*xChild);
1247 {
1248 const SwRangeRedline& rRedln = pSh->GetRedline( nPos );
1249 bIsNotFormated |= RedlineType::Format != rRedln.GetType();
1250
1251 if (pSh->GotoRedline(nPos, true))
1252 {
1253 pSh->SetInSelect();
1254 pSh->EnterAddMode();
1255 }
1256 }
1257 }
1258 while ( rTreeView.iter_next_sibling(*xChild) );
1259 }
1260 }
1261 return false;
1262 });
1263
1264 pSh->LeaveAddMode();
1265 pSh->EndAction();
1267 }
1268 }
1269
1270 bool const bEnable = !pSh->GetDoc()->GetDocShell()->IsReadOnly()
1271 && !pSh->getIDocumentRedlineAccess().GetRedlinePassword().hasElements();
1272 m_pTPView->EnableAccept( bEnable && bSel /*&& !bReadonlySel*/ );
1273 m_pTPView->EnableReject( bEnable && bSel /*&& !bReadonlySel*/ );
1274 m_pTPView->EnableClearFormat( bEnable && bSel && !bIsNotFormated /*&& !bReadonlySel*/ );
1275 m_pTPView->EnableAcceptAll( bEnable );
1276 m_pTPView->EnableRejectAll( bEnable );
1277 m_pTPView->EnableClearFormatAll( bEnable && m_bOnlyFormatedRedlines );
1278}
1279
1280IMPL_LINK(SwRedlineAcceptDlg, CommandHdl, const CommandEvent&, rCEvt, bool)
1281{
1282 if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
1283 return false;
1284
1285 SwView* pView = GetActiveView();
1286 if (!pView)
1287 return false;
1288
1289 SwWrtShell* pSh = pView->GetWrtShellPtr();
1290 if (!pSh)
1291 return false;
1292
1293 const SwRangeRedline *pRed = nullptr;
1294
1295 weld::TreeView& rTreeView = m_pTable->GetWidget();
1296 std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
1297 bool bEntry = rTreeView.get_selected(xEntry.get());
1298 if (bEntry)
1299 {
1300 std::unique_ptr<weld::TreeIter> xTopEntry(rTreeView.make_iterator(xEntry.get()));
1301
1302 if (rTreeView.get_iter_depth(*xTopEntry))
1303 rTreeView.iter_parent(*xTopEntry);
1304
1305 SwRedlineTable::size_type nPos = GetRedlinePos(*xTopEntry);
1306
1307 // disable commenting for protected areas
1308 if (nPos != SwRedlineTable::npos && (pRed = pSh->GotoRedline(nPos, true)) != nullptr)
1309 {
1310 if( pSh->IsCursorPtAtEnd() )
1311 pSh->SwapPam();
1312 pSh->SetInSelect();
1313 }
1314 }
1315
1316 m_xPopup->set_sensitive("writeredit", bEntry && pRed &&
1317 !rTreeView.get_iter_depth(*xEntry) &&
1318 rTreeView.count_selected_rows() == 1);
1319 m_xPopup->set_sensitive("writersort", rTreeView.n_children() != 0);
1320 int nColumn = rTreeView.get_sort_column();
1321 if (nColumn == -1)
1322 nColumn = 4;
1323 for (sal_Int32 i = 0; i < 5; ++i)
1324 m_xSortMenu->set_active(u"writersort" + OUString::number(i), i == nColumn);
1325
1326 OUString sCommand = m_xPopup->popup_at_rect(&rTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
1327
1328 if (sCommand == "writeredit")
1329 {
1330 if (bEntry)
1331 {
1332 if (rTreeView.get_iter_depth(*xEntry))
1333 rTreeView.iter_parent(*xEntry);
1334
1335 SwRedlineTable::size_type nPos = GetRedlinePos(*xEntry);
1336
1338 return true;
1339
1340 const SwRangeRedline &rRedline = pSh->GetRedline(nPos);
1341
1342 /* enable again once we have redline comments in the margin
1343 sComment = rRedline.GetComment();
1344 if ( !sComment.Len() )
1345 GetActiveView()->GetDocShell()->Broadcast(SwRedlineHint(&rRedline,SWREDLINE_INSERTED));
1346 const_cast<SwRangeRedline&>(rRedline).Broadcast(SwRedlineHint(&rRedline,SWREDLINE_FOCUS));
1347 */
1348
1349 OUString sComment = convertLineEnd(rRedline.GetComment(), GetSystemLineEnd());
1351 ::DialogGetRanges fnGetRange = pFact->GetDialogGetRangesFunc();
1352 SfxItemSet aSet( pSh->GetAttrPool(), fnGetRange() );
1353
1354 aSet.Put(SvxPostItTextItem(sComment, SID_ATTR_POSTIT_TEXT));
1355 aSet.Put(SvxPostItAuthorItem(rRedline.GetAuthorString(), SID_ATTR_POSTIT_AUTHOR));
1356
1358 rRedline.GetRedlineData().GetTimeStamp() ),
1359 SID_ATTR_POSTIT_DATE ));
1360
1361 ScopedVclPtr<AbstractSvxPostItDialog> pDlg(pFact->CreateSvxPostItDialog(&rTreeView, aSet));
1362
1363 pDlg->HideAuthor();
1364
1365 TranslateId pResId;
1366 switch( rRedline.GetType() )
1367 {
1368 case RedlineType::Insert:
1369 pResId = STR_REDLINE_INSERTED;
1370 break;
1371 case RedlineType::Delete:
1372 pResId = STR_REDLINE_DELETED;
1373 break;
1374 case RedlineType::Format:
1375 case RedlineType::ParagraphFormat:
1376 pResId = STR_REDLINE_FORMATTED;
1377 break;
1378 case RedlineType::Table:
1379 pResId = STR_REDLINE_TABLECHG;
1380 break;
1381 default:;//prevent warning
1382 }
1383 OUString sTitle(SwResId(STR_REDLINE_COMMENT));
1384 if (pResId)
1385 sTitle += SwResId(pResId);
1386 pDlg->SetText(sTitle);
1387
1388 SwViewShell::SetCareDialog(pDlg->GetDialog());
1389
1390 if ( pDlg->Execute() == RET_OK )
1391 {
1392 const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
1393 OUString sMsg(pOutSet->Get(SID_ATTR_POSTIT_TEXT).GetValue());
1394
1395 // insert / change comment
1396 pSh->SetRedlineComment(sMsg);
1397 rTreeView.set_text(*xEntry, sMsg.replace('\n', ' '), 3);
1398 Init();
1399 }
1400
1402 pDlg.disposeAndClear();
1403 }
1404 }
1405 else if (!sCommand.isEmpty())
1406 {
1407 int nSortMode = o3tl::toInt32(sCommand.subView(10));
1408
1409 if (nSortMode == 4 && nColumn == 4)
1410 return true; // we already have it
1411 if (nSortMode == 4)
1412 nSortMode = -1; // unsorted / sorted by position
1413
1414 SwWait aWait( *pView->GetDocShell(), false );
1415 m_pTable->HeaderBarClick(nSortMode);
1416 if (nSortMode == -1)
1417 Init(); // newly fill everything
1418 }
1419 return true;
1420}
1421
1422namespace
1423{
1424 OUString lcl_StripAcceptChgDat(OUString &rExtraString)
1425 {
1426 OUString aStr;
1427 while(true)
1428 {
1429 sal_Int32 nPos = rExtraString.indexOf("AcceptChgDat:");
1430 if (nPos == -1)
1431 break;
1432 // try to read the alignment string "ALIGN:(...)"; if none existing,
1433 // it's an old version
1434 sal_Int32 n1 = rExtraString.indexOf('(', nPos);
1435 if (n1 != -1)
1436 {
1437 sal_Int32 n2 = rExtraString.indexOf(')', n1);
1438 if (n2 != -1)
1439 {
1440 // cut out the alignment string
1441 aStr = rExtraString.copy(nPos, n2 - nPos + 1);
1442 rExtraString = rExtraString.replaceAt(nPos, n2 - nPos + 1, u"");
1443 aStr = aStr.copy(n1 - nPos + 1);
1444 }
1445 }
1446 }
1447 return aStr;
1448 }
1449}
1450
1451void SwRedlineAcceptDlg::Initialize(OUString& rExtraString)
1452{
1453 if (rExtraString.isEmpty())
1454 return;
1455
1456 OUString aStr = lcl_StripAcceptChgDat(rExtraString);
1457 if (aStr.isEmpty())
1458 return;
1459
1460 int nCount = aStr.toInt32();
1461 if (nCount <= 2)
1462 return;
1463
1464 std::vector<int> aEndPos;
1465
1466 for (int i = 0; i < nCount; ++i)
1467 {
1468 sal_Int32 n1 = aStr.indexOf(';');
1469 aStr = aStr.copy( n1+1 );
1470 aEndPos.push_back(aStr.toInt32());
1471 }
1472
1473 bool bUseless = false;
1474
1475 std::vector<int> aWidths;
1476 for (int i = 1; i < nCount; ++i)
1477 {
1478 aWidths.push_back(aEndPos[i] - aEndPos[i - 1]);
1479 if (aWidths.back() <= 0)
1480 bUseless = true;
1481 }
1482
1483 if (!bUseless)
1484 {
1485 // turn column end points back to column widths, ignoring the small
1486 // value used for the expander column
1487 weld::TreeView& rTreeView = m_pTable->GetWidget();
1488 rTreeView.set_column_fixed_widths(aWidths);
1489 }
1490}
1491
1492void SwRedlineAcceptDlg::FillInfo(OUString &rExtraData) const
1493{
1494 //remove any old one before adding a new one
1495 lcl_StripAcceptChgDat(rExtraData);
1496 rExtraData += "AcceptChgDat:(";
1497
1498 const int nTabCount = 4;
1499
1500 rExtraData += OUString::number(nTabCount);
1501 rExtraData += ";";
1502
1503 weld::TreeView& rTreeView = m_pTable->GetWidget();
1504 std::vector<int> aWidths;
1505 // turn column widths back into column end points for compatibility
1506 // with how they used to be stored, including a small value for the
1507 // expander column
1508 aWidths.push_back(rTreeView.get_checkbox_column_width());
1509 for (int i = 0; i < nTabCount - 1; ++i)
1510 {
1511 int nWidth = rTreeView.get_column_width(i);
1512 assert(nWidth > 0 && "suspicious to get a value like this");
1513 aWidths.push_back(aWidths.back() + nWidth);
1514 }
1515
1516 for (auto a : aWidths)
1517 {
1518 rExtraData += OUString::number(a);
1519 rExtraData += ";";
1520 }
1521 rExtraData += ")";
1522}
1523
1525 : PanelLayout(pParent, "ManageChangesPanel", "modules/swriter/ui/managechangessidebar.ui")
1526 , mxContentArea(m_xBuilder->weld_container("content_area"))
1527{
1528 mpImplDlg.reset(new SwRedlineAcceptDlg(nullptr, m_xBuilder.get(), mxContentArea.get()));
1529
1530 mpImplDlg->Init();
1531
1532 // we want to receive SfxHintId::DocChanged
1533 StartListening(*(SW_MOD()->GetView()->GetDocShell()));
1534}
1535
1537{
1538}
1539
1541{
1542 if (mpImplDlg && rHint.GetId() == SfxHintId::DocChanged)
1543 mpImplDlg->Activate();
1544}
1545
1546/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@ UndoArg1
Definition: SwRewriter.hxx:29
SFX_IMPL_MODELESSDIALOGCONTOLLER_WITHID(SvxContourDlgChildWindow, SID_CONTOUR_DLG)
Reference< XExecutableDialog > m_xDialog
virtual const css::uno::Sequence< sal_Int8 > & GetRedlinePassword() const =0
std::unique_ptr< weld::Builder > m_xBuilder
std::shared_ptr< SfxDialogController > & GetController()
const SfxPoolItem * ExecuteList(sal_uInt16 nSlot, SfxCallMode nCall, std::initializer_list< SfxPoolItem const * > args, std::initializer_list< SfxPoolItem const * > internalargs=std::initializer_list< SfxPoolItem const * >())
SfxHintId GetId() const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
virtual void FillInfo(SfxChildWinInfo &) const
void Initialize(SfxChildWinInfo const *pInfo)
virtual void Activate() override
bool IsReadOnly() const
SfxDispatcher * GetDispatcher()
SfxViewFrame & GetViewFrame() const
virtual VclPtr< AbstractSvxPostItDialog > CreateSvxPostItDialog(weld::Widget *pParent, const SfxItemSet &rCoreSet, bool bPrevNext=false)=0
static SvxAbstractDialogFactory * Create()
virtual DialogGetRanges GetDialogGetRangesFunc()=0
bool IsSorted() const
bool IsValidEntry(std::u16string_view rAuthor, const DateTime &rDateTime, const OUString &rComment)
void SetWriterView()
weld::TreeView & GetWidget()
void ClearAuthors()
OUString GetSelectedAuthor() const
weld::ComboBox * GetLbAction()
void InsertAuthor(const OUString &rString)
bool IsAction() const
sal_Int32 SelectAuthor(const OUString &aString)
void EnableRejectAll(bool bFlag)
void EnableAccept(bool bFlag)
void EnableClearFormat(bool bFlag)
SvxRedlinTable * GetTableControl()
void SetRejectClickHdl(const Link< SvxTPView *, void > &rLink)
void EnableUndo(bool bFlag=true)
void EnableAcceptAll(bool bFlag)
void SetUndoClickHdl(const Link< SvxTPView *, void > &rLink)
void SetRejectAllClickHdl(const Link< SvxTPView *, void > &rLink)
void SetAcceptClickHdl(const Link< SvxTPView *, void > &rLink)
void EnableReject(bool bFlag)
void DisableUndo()
void ShowUndo()
void SetAcceptAllClickHdl(const Link< SvxTPView *, void > &rLink)
void EnableClearFormatAll(bool bFlag)
virtual bool ReInitDlg(SwDocShell *pDocSh)
Definition: fldwrap.cxx:46
void SetOldDocShell(SwDocShell *pDcSh)
Definition: chldwrap.hxx:42
SwDocShell * GetOldDocShell()
Definition: chldwrap.hxx:41
void StartAction()
Definition: crsrsh.cxx:226
void SwapPam()
Definition: crsrsh.cxx:1262
void EndAction(const bool bIdleEnd=false)
Definition: crsrsh.cxx:243
const SwRangeRedline * SelNextRedline()
Definition: crstrvl.cxx:2477
const SwRangeRedline * SelPrevRedline()
Definition: crstrvl.cxx:2504
bool IsCursorPtAtEnd() const
Definition: crsrsh.hxx:920
SwDocShell * GetDocShell()
Definition: doc.hxx:1370
bool IsModified() const
Changes in document?
Definition: edws.cxx:65
bool AcceptRedline(SwRedlineTable::size_type nPos)
Definition: edredln.cxx:67
bool SetRedlineComment(const OUString &rS)
Set comment to Redline at position.
Definition: edredln.cxx:150
SwUndoId StartUndo(SwUndoId eUndoId=SwUndoId::EMPTY, const SwRewriter *pRewriter=nullptr)
Undo: set up Undo parenthesis, return nUndoId of this parenthesis.
Definition: edws.cxx:223
bool RejectRedline(SwRedlineTable::size_type nPos)
Definition: edredln.cxx:78
void ResetModified()
Definition: edws.cxx:75
const SwRangeRedline & GetRedline(SwRedlineTable::size_type nPos) const
Definition: edredln.cxx:53
const SwRangeRedline * GetCurrRedline() const
Definition: edredln.cxx:161
SwUndoId EndUndo(SwUndoId eUndoId=SwUndoId::EMPTY, const SwRewriter *pRewriter=nullptr)
Closes parenthesis of nUndoId, not used by UI.
Definition: edws.cxx:234
SwRedlineTable::size_type GetRedlineCount() const
Definition: edredln.cxx:48
SwRedlineTable::size_type FindRedlineOfData(const SwRedlineData &) const
Search Redline for this Data and.
Definition: edredln.cxx:186
SwModelessRedlineAcceptDlg(SfxBindings *, SwChildWinWrapper *, weld::Window *pParent)
Definition: redlndlg.cxx:81
virtual void FillInfo(SfxChildWinInfo &) const override
Definition: redlndlg.cxx:133
void Initialize(SfxChildWinInfo *pInfo)
Definition: redlndlg.cxx:125
virtual void Activate() override
Definition: redlndlg.cxx:91
std::unique_ptr< SwRedlineAcceptDlg > m_xImplDlg
Definition: redlndlg.hxx:132
std::unique_ptr< weld::Container > m_xContentArea
Definition: redlndlg.hxx:131
SwChildWinWrapper * m_pChildWin
Definition: redlndlg.hxx:133
virtual ~SwModelessRedlineAcceptDlg() override
Definition: redlndlg.cxx:139
SwTableBox * GetTableBox() const
If node is in a table return the respective table box.
Definition: node.cxx:772
const SwPosition * Start() const
Definition: pam.hxx:258
bool IsAutoFormat() const
Definition: redline.hxx:213
const OUString & GetComment(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1985
sal_uInt16 GetStackCount() const
Definition: docredln.cxx:1952
OUString const & GetAuthorString(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1965
bool IsAnnotation() const
Definition: docredln.cxx:1980
bool IsMoved() const
Definition: redline.hxx:282
const DateTime & GetTimeStamp(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1970
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1975
const SwRedlineData & GetRedlineData(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1998
virtual bool ReInitDlg(SwDocShell *pDocSh) override
Definition: redlndlg.cxx:72
bool HasRedlineAutoFormat() const
Definition: redlndlg.hxx:118
OUString m_sFormated
Definition: redlndlg.hxx:69
void FillInfo(OUString &rExtraData) const
Definition: redlndlg.cxx:1492
OUString m_sFilterAction
Definition: redlndlg.hxx:72
SAL_DLLPRIVATE void InitAuthors()
Definition: redlndlg.cxx:242
OUString m_sInserted
Definition: redlndlg.hxx:67
void Init(SwRedlineTable::size_type nStart=0)
Definition: redlndlg.cxx:212
OUString m_sDeleted
Definition: redlndlg.hxx:68
std::vector< std::unique_ptr< SwRedlineDataChild > > m_RedlineChildren
Definition: redlndlg.hxx:61
SAL_DLLPRIVATE OUString GetActionText(const SwRangeRedline &rRedln, sal_uInt16 nStack=0)
Definition: redlndlg.cxx:349
SvxTPView * m_pTPView
Definition: redlndlg.hxx:85
OUString m_sAutoFormat
Definition: redlndlg.hxx:73
void Initialize(OUString &rExtraData)
Definition: redlndlg.cxx:1451
SAL_DLLPRIVATE void RemoveParents(SwRedlineTable::size_type nStart, SwRedlineTable::size_type nEnd)
Definition: redlndlg.cxx:673
void CallAcceptReject(bool bSelect, bool bAccept)
Definition: redlndlg.cxx:968
bool m_bOnlyFormatedRedlines
Definition: redlndlg.hxx:74
OUString m_sFormatCollSet
Definition: redlndlg.hxx:71
SAL_DLLPRIVATE void InsertChildren(SwRedlineDataParent *pParent, const SwRangeRedline &rRedln, bool bHasRedlineAutoFormat)
Definition: redlndlg.cxx:574
SAL_DLLPRIVATE SwRedlineTable::size_type GetRedlinePos(const weld::TreeIter &rEntry)
Definition: redlndlg.cxx:1116
std::unique_ptr< SvxAcceptChgCtr > m_xTabPagesCTRL
Definition: redlndlg.hxx:83
SAL_DLLPRIVATE SwRedlineTable::size_type CalcDiff(SwRedlineTable::size_type nStart, bool bChild)
Definition: redlndlg.cxx:491
SwRedlineAcceptDlg(SwRedlineAcceptDlg const &)=delete
SAL_DLLPRIVATE void InsertParents(SwRedlineTable::size_type nStart, SwRedlineTable::size_type nEnd=SwRedlineTable::npos)
Definition: redlndlg.cxx:756
static SAL_DLLPRIVATE OUString GetActionImage(const SwRangeRedline &rRedln, sal_uInt16 nStack=0, bool bTableChanges=false, bool bRowChanges=false)
Definition: redlndlg.cxx:316
OUString m_sTableChgd
Definition: redlndlg.hxx:70
bool m_bHasTrackedColumn
Definition: redlndlg.hxx:81
SwRedlineDataParentSortArr m_aUsedSeqNo
Definition: redlndlg.hxx:65
std::vector< std::unique_ptr< SwRedlineDataParent > > m_RedlineParents
Definition: redlndlg.hxx:59
std::vector< std::unique_ptr< RedlinData > > m_RedlinData
Definition: redlndlg.hxx:64
SvxRedlinTable * m_pTable
Definition: redlndlg.hxx:86
std::unique_ptr< SwRedlineAcceptDlg > mpImplDlg
Definition: redlndlg.hxx:160
SwRedlineAcceptPanel(weld::Widget *pParent)
Definition: redlndlg.cxx:1524
std::unique_ptr< weld::Container > mxContentArea
Definition: redlndlg.hxx:161
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
We need to be a SfxListener to be able to update the list of changes when we get SfxHintId::DocChange...
Definition: redlndlg.cxx:1540
virtual ~SwRedlineAcceptPanel() override
Definition: redlndlg.cxx:1536
sal_uInt16 GetSeqNo() const
Definition: redline.hxx:156
const SwRedlineData * Next() const
Definition: redline.hxx:137
bool CanCombine(const SwRedlineData &rCmp) const
Definition: docredln.cxx:1097
const DateTime & GetTimeStamp() const
Definition: redline.hxx:130
static constexpr size_type npos
Definition: docary.hxx:224
vector_type::size_type size_type
Definition: docary.hxx:223
void AddRule(SwUndoArg eWhat, const OUString &rWith)
Definition: SwRewriter.cxx:25
OUString Apply(const OUString &rStr) const
Definition: SwRewriter.cxx:39
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:443
SwTableLine * GetUpper()
Definition: swtable.hxx:477
SwRedlineTable::size_type GetRedline() const
Definition: swtable.cxx:2987
RedlineType GetRedlineType() const
Definition: swtable.cxx:3025
SwTableLine is one table row in the document model.
Definition: swtable.hxx:376
SwRedlineTable::size_type UpdateTextChangesOnly(SwRedlineTable::size_type &rRedlinePos, bool bUpdateProperty=true) const
Definition: swtable.cxx:1751
RedlineType GetRedlineType() const
Definition: swtable.cxx:1954
static void SetCareDialog(const std::shared_ptr< weld::Window > &rNew)
Definition: viewsh.cxx:2669
SwDoc * GetDoc() const
Definition: viewsh.hxx:308
const IDocumentRedlineAccess & getIDocumentRedlineAccess() const
Provides access to the document redline interface.
Definition: viewsh.cxx:2825
const SfxItemPool & GetAttrPool() const
Definition: viewsh.hxx:648
Definition: view.hxx:146
SwWrtShell * GetWrtShellPtr() const
Definition: view.hxx:424
SwDocShell * GetDocShell()
Definition: view.cxx:1193
Used by the UI to modify the document model.
Definition: wrtsh.hxx:97
const SwRangeRedline * GotoRedline(SwRedlineTable::size_type nArrPos, bool bSelect)
Definition: move.cxx:755
void LeaveAddMode()
Definition: select.cxx:650
void EnterStdMode()
Definition: select.cxx:560
void SetInSelect()
Definition: wrtsh.hxx:145
void EnterAddMode()
Definition: select.cxx:635
const SwView & GetView() const
Definition: wrtsh.hxx:443
void SetTimeout(sal_uInt64 nTimeoutMs)
void SetInvokeHandler(const Link< Timer *, void > &rLink)
void disposeAndClear()
size_type erase(const Value &x)
std::pair< const_iterator, bool > insert(Value &&x)
virtual OUString get_active_text() const=0
virtual void set_active(int pos)=0
void append_text(const OUString &rStr)
virtual void scroll_to_row(int row)=0
virtual std::unique_ptr< TreeIter > make_iterator(const TreeIter *pOrig=nullptr) const=0
virtual bool get_selected(TreeIter *pIter) const=0
virtual void connect_popup_menu(const Link< const CommandEvent &, bool > &rLink)
virtual void make_sorted()=0
virtual void expand_row(const TreeIter &rIter)=0
virtual int get_iter_index_in_parent(const TreeIter &rIter) const=0
virtual void set_text(int row, const OUString &rText, int col=-1)=0
int get_checkbox_column_width() const
virtual int n_children() const=0
void unselect_all()
virtual void set_selection_mode(SelectionMode eMode)=0
virtual int get_sort_column() const=0
virtual void insert(const TreeIter *pParent, int pos, const OUString *pStr, const OUString *pId, const OUString *pIconName, VirtualDevice *pImageSurface, bool bChildrenOnDemand, TreeIter *pRet)=0
virtual void clear()=0
virtual int iter_n_children(const TreeIter &rIter) const=0
virtual void selected_foreach(const std::function< bool(TreeIter &)> &func)=0
void connect_changed(const Link< TreeView &, void > &rLink)
virtual void set_image(int row, const OUString &rImage, int col=-1)=0
virtual void copy_iterator(const TreeIter &rSource, TreeIter &rDest) const=0
virtual void remove(int pos)=0
virtual bool iter_next_sibling(TreeIter &rIter) const=0
virtual void select(int pos)=0
virtual bool iter_parent(TreeIter &rIter) const=0
virtual void set_column_fixed_widths(const std::vector< int > &rWidths)=0
virtual bool iter_children(TreeIter &rIter) const=0
virtual int get_column_width(int nCol) const=0
virtual void set_cursor(int pos)=0
virtual int get_iter_depth(const TreeIter &rIter) const=0
virtual void all_foreach(const std::function< bool(TreeIter &)> &func)=0
virtual void make_unsorted()=0
virtual int count_selected_rows() const=0
virtual OUString get_id(int pos) const=0
virtual void freeze()=0
virtual void thaw()=0
#define FN_REDLINE_ACCEPT
Definition: cmdid.h:136
#define FN_REDLINE_SHOW
Definition: cmdid.h:131
void Init()
int nCount
float u
uno_Any a
LineEnd GetSystemLineEnd()
TOOLS_DLLPUBLIC OString convertLineEnd(const OString &rIn, LineEnd eLineEnd)
sal_uInt16 nPos
aStr
std::unique_ptr< sal_Int32[]> pData
int n2
int n1
int i
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
const ::avmedia::MediaItem * Execute(const SdrMarkView *pSdrView, SfxRequest const &rReq)
OUString toId(const void *pValue)
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
IMPL_LINK_NOARG(SwRedlineAcceptDlg, AcceptHdl, SvxTPView *, void)
Definition: redlndlg.cxx:1131
IMPL_LINK(SwRedlineAcceptDlg, CommandHdl, const CommandEvent &, rCEvt, bool)
Definition: redlndlg.cxx:1280
OUString aExtraString
SwNode & GetNode() const
Definition: pam.hxx:81
const SwRedlineData * pChild
Definition: redlndlg.hxx:38
std::unique_ptr< weld::TreeIter > xTLBChild
Definition: redlndlg.hxx:40
const SwRedlineDataChild * pNext
Definition: redlndlg.hxx:39
std::unique_ptr< weld::TreeIter > xTLBParent
Definition: redlndlg.hxx:47
const SwRedlineDataChild * pNext
Definition: redlndlg.hxx:46
const SwRedlineData * pData
Definition: redlndlg.hxx:45
SwView * GetActiveView()
Definition: swmodul1.cxx:115
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:168
#define SW_MOD()
Definition: swmodule.hxx:254
@ REJECT_REDLINE
@ ACCEPT_REDLINE
OUString GetAppLangDateTimeString(const DateTime &)
Definition: uitool.cxx:863
OUString sId
RET_OK