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_xDialog->weld_content_area())
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_xTabPagesCTRL(new SvxAcceptChgCtr(pContentArea))
157 , m_xPopup(pBuilder->weld_menu("writermenu"))
158 , m_xSortMenu(pBuilder->weld_menu("writersortmenu"))
159{
160 m_pTPView = m_xTabPagesCTRL->GetViewPage();
161
164
170 //tdf#89227 default to disabled, and only enable if possible to accept/reject
171 m_pTPView->EnableAccept(false);
172 m_pTPView->EnableReject(false);
177
178 m_xTabPagesCTRL->GetFilterPage()->SetReadyHdl(LINK(this, SwRedlineAcceptDlg, FilterChangedHdl));
179
180 weld::ComboBox* pActLB = m_xTabPagesCTRL->GetFilterPage()->GetLbAction();
181 pActLB->append_text(m_sInserted);
182 pActLB->append_text(m_sDeleted);
183 pActLB->append_text(m_sFormated);
184 pActLB->append_text(m_sTableChgd);
185
187 {
189 pActLB->append_text(m_sAutoFormat);
191 m_pTPView->DisableUndo(); // no UNDO events yet
192 }
193
194 pActLB->set_active(0);
195
196 weld::TreeView& rTreeView = m_pTable->GetWidget();
197 rTreeView.set_selection_mode(SelectionMode::Multiple);
198
199 rTreeView.connect_changed(LINK(this, SwRedlineAcceptDlg, SelectHdl));
200 rTreeView.connect_popup_menu(LINK(this, SwRedlineAcceptDlg, CommandHdl));
201
202 // avoid multiple selection of the same texts:
205}
206
208{
209}
210
212{
213 std::optional<SwWait> oWait;
214 if (SwView *pView = GetActiveView())
215 oWait.emplace(*pView->GetDocShell(), false);
216 weld::TreeView& rTreeView = m_pTable->GetWidget();
218
219 rTreeView.freeze();
220 if (nStart)
221 RemoveParents(nStart, m_RedlineParents.size() - 1);
222 else
223 {
224 rTreeView.clear();
225 m_RedlinData.clear();
226 m_RedlineChildren.clear();
227 m_RedlineParents.erase(m_RedlineParents.begin() + nStart, m_RedlineParents.end());
228 }
229 rTreeView.thaw();
230
231 // insert parents
232 InsertParents(nStart);
233 InitAuthors();
234
235 // #i69618# this moves the list box to the right position, visually
236 std::unique_ptr<weld::TreeIter> xSelEntry(rTreeView.make_iterator());
237 if (rTreeView.get_selected(xSelEntry.get()))
238 rTreeView.scroll_to_row(*xSelEntry); //#i70937#, force the scroll
239}
240
242{
243 if (!m_xTabPagesCTRL)
244 return;
245
246 SwView *pView = ::GetActiveView();
247 if (!pView)
248 return;
249 SwWrtShell* pSh = pView->GetWrtShellPtr();
250
251 SvxTPFilter *pFilterPage = m_xTabPagesCTRL->GetFilterPage();
252
253 std::vector<OUString> aStrings;
254 OUString sOldAuthor(pFilterPage->GetSelectedAuthor());
255 pFilterPage->ClearAuthors();
256
258
260 bool bIsNotFormated = false;
261
262 // determine authors
263 for ( SwRedlineTable::size_type i = 0; i < nCount; i++)
264 {
265 const SwRangeRedline& rRedln = pSh->GetRedline(i);
266
267 if( m_bOnlyFormatedRedlines && RedlineType::Format != rRedln.GetType() )
269
270 aStrings.push_back(rRedln.GetAuthorString());
271
272 for (sal_uInt16 nStack = 1; nStack < rRedln.GetStackCount(); nStack++)
273 {
274 aStrings.push_back(rRedln.GetAuthorString(nStack));
275 }
276 }
277
278 std::sort(aStrings.begin(), aStrings.end());
279 aStrings.erase(std::unique(aStrings.begin(), aStrings.end()), aStrings.end());
280
281 for (auto const & i: aStrings)
282 pFilterPage->InsertAuthor(i);
283
284 if (pFilterPage->SelectAuthor(sOldAuthor) == -1 && !aStrings.empty())
285 pFilterPage->SelectAuthor(aStrings[0]);
286
287 weld::TreeView& rTreeView = m_pTable->GetWidget();
288 bool const bEnable = pSh && !pSh->GetDoc()->GetDocShell()->IsReadOnly()
289 && rTreeView.n_children() != 0
290 && !pSh->getIDocumentRedlineAccess().GetRedlinePassword().hasElements();
291 bool bSel = rTreeView.get_selected(nullptr);
292
293 rTreeView.selected_foreach([this, pSh, &bIsNotFormated](weld::TreeIter& rEntry){
294 // find the selected redline
295 // (fdo#57874: ignore, if the redline is already gone)
298 {
299 const SwRangeRedline& rRedln = pSh->GetRedline( nPos );
300
301 bIsNotFormated |= RedlineType::Format != rRedln.GetType();
302 }
303 return false;
304 });
305
306 m_pTPView->EnableAccept( bEnable && bSel );
307 m_pTPView->EnableReject( bEnable && bSel );
308 m_pTPView->EnableClearFormat( bEnable && !bIsNotFormated && bSel );
309 m_pTPView->EnableAcceptAll( bEnable );
310 m_pTPView->EnableRejectAll( bEnable );
313}
314
315OUString SwRedlineAcceptDlg::GetActionImage(const SwRangeRedline& rRedln, sal_uInt16 nStack, bool bRowChanges)
316{
317 switch (rRedln.GetType(nStack))
318 {
319 case RedlineType::Insert: return bRowChanges
320 ? OUString(BMP_REDLINE_ROW_INSERTION)
321 : rRedln.IsMoved()
322 ? OUString(BMP_REDLINE_MOVED_INSERTION)
323 : rRedln.IsAnnotation()
324 ? OUString(BMP_REDLINE_COMMENT_INSERTION)
325 : OUString(BMP_REDLINE_INSERTED);
326 case RedlineType::Delete: return bRowChanges
327 ? OUString(BMP_REDLINE_ROW_DELETION)
328 : rRedln.IsMoved()
329 ? OUString(BMP_REDLINE_MOVED_DELETION)
330 : rRedln.IsAnnotation()
331 ? OUString(BMP_REDLINE_COMMENT_DELETION)
332 : OUString(BMP_REDLINE_DELETED);
333 case RedlineType::Format: return BMP_REDLINE_FORMATTED;
334 case RedlineType::ParagraphFormat: return BMP_REDLINE_FORMATTED;
335 case RedlineType::Table: return BMP_REDLINE_TABLECHG;
336 case RedlineType::FmtColl: return BMP_REDLINE_FMTCOLLSET;
337 default: break;
338 }
339
340 return OUString();
341}
342
343OUString SwRedlineAcceptDlg::GetActionText(const SwRangeRedline& rRedln, sal_uInt16 nStack)
344{
345 switch( rRedln.GetType(nStack) )
346 {
347 case RedlineType::Insert: return m_sInserted;
348 case RedlineType::Delete: return m_sDeleted;
349 case RedlineType::Format: return m_sFormated;
350 case RedlineType::ParagraphFormat: return m_sFormated;
351 case RedlineType::Table: return m_sTableChgd;
352 case RedlineType::FmtColl: return m_sFormatCollSet;
353 default:;//prevent warning
354 }
355
356 return OUString();
357}
358
359// newly initialise after activation
361{
362 // prevent update if flag is set (#102547#)
364 return;
365
366 SwView *pView = ::GetActiveView();
367 if (!pView) // can happen when switching to another app
368 {
369 m_pTPView->EnableAccept(false);
370 m_pTPView->EnableReject(false);
375 return; // had the focus previously
376 }
377
378 SwWait aWait( *pView->GetDocShell(), false );
379
380 if (pView->GetDocShell()->IsReadOnly())
381 {
382 m_pTPView->EnableAccept(false);
383 m_pTPView->EnableReject(false);
388 // note: enabling is done in InitAuthors below
389 }
390
392
393 // did something change?
394 SwWrtShell* pSh = pView->GetWrtShellPtr();
395 if (!pSh)
396 return;
397
399
400 // check the number of pointers
401 for ( SwRedlineTable::size_type i = 0; i < nCount; i++)
402 {
403 const SwRangeRedline& rRedln = pSh->GetRedline(i);
404
405 if (i >= m_RedlineParents.size())
406 {
407 // new entries have been appended
408 Init(i);
409 return;
410 }
411
412 SwRedlineDataParent *const pParent = m_RedlineParents[i].get();
413 if (&rRedln.GetRedlineData() != pParent->pData)
414 {
415 // Redline-Parents were inserted, changed or deleted
416 i = CalcDiff(i, false);
417 if (i == SwRedlineTable::npos)
418 return;
419 continue;
420 }
421
422 const SwRedlineData *pRedlineData = rRedln.GetRedlineData().Next();
423 const SwRedlineDataChild *pBackupData = pParent->pNext;
424
425 if (!pRedlineData && pBackupData)
426 {
427 // Redline-Children were deleted
428 i = CalcDiff(i, true);
429 if (i == SwRedlineTable::npos)
430 return;
431 continue;
432 }
433 else
434 {
435 while (pRedlineData)
436 {
437 if (pRedlineData != pBackupData->pChild)
438 {
439 // Redline-Children were inserted, changed or deleted
440 i = CalcDiff(i, true);
441 if (i == SwRedlineTable::npos)
442 return;
443 continue;
444 }
445 pBackupData = pBackupData->pNext;
446 pRedlineData = pRedlineData->Next();
447 }
448 }
449 }
450
451 if (nCount != m_RedlineParents.size())
452 {
453 // Redlines were deleted at the end
454 Init(nCount);
455 return;
456 }
457
458 // check comment
459 weld::TreeView& rTreeView = m_pTable->GetWidget();
460 bool bIsShowChangesInMargin = SW_MOD()->GetUsrPref(false)->IsShowChangesInMargin();
461 for (SwRedlineTable::size_type i = 0; i < nCount; i++)
462 {
463 const SwRangeRedline& rRedln = pSh->GetRedline(i);
464 SwRedlineDataParent *const pParent = m_RedlineParents[i].get();
465
466 if(rRedln.GetComment() != pParent->sComment)
467 {
468 bool bShowDeletedTextAsComment = bIsShowChangesInMargin &&
469 RedlineType::Delete == rRedln.GetType() && rRedln.GetComment().isEmpty();
470 const OUString sComment = bShowDeletedTextAsComment
471 ? const_cast<SwRangeRedline&>(rRedln).GetDescr()
472 : rRedln.GetComment();
473 if (pParent->xTLBParent)
474 {
475 // update only comment
476 rTreeView.set_text(*pParent->xTLBParent, sComment.replace('\n', ' '), 3);
477 }
478 pParent->sComment = sComment;
479 }
480 }
481
482 InitAuthors();
483}
484
486{
487 if (!nStart)
488 {
489 Init();
491 }
492
493 weld::TreeView& rTreeView = m_pTable->GetWidget();
494 rTreeView.freeze();
495 SwView *pView = ::GetActiveView();
496 if (!pView)
498
499 SwWrtShell* pSh = pView->GetWrtShellPtr();
500 if (!pSh)
502
503 bool bHasRedlineAutoFormat = HasRedlineAutoFormat();
504 SwRedlineDataParent *const pParent = m_RedlineParents[nStart].get();
505 const SwRangeRedline& rRedln = pSh->GetRedline(nStart);
506
507 if (bChild) // should actually never happen, but just in case...
508 {
509 // throw away all entry's children and initialise newly
510 SwRedlineDataChild* pBackupData = const_cast<SwRedlineDataChild*>(pParent->pNext);
511 SwRedlineDataChild* pNext;
512
513 while (pBackupData)
514 {
515 pNext = const_cast<SwRedlineDataChild*>(pBackupData->pNext);
516 if (pBackupData->xTLBChild)
517 rTreeView.remove(*pBackupData->xTLBChild);
518
519 auto it = std::find_if(m_RedlineChildren.begin(), m_RedlineChildren.end(),
520 [&pBackupData](const std::unique_ptr<SwRedlineDataChild>& rChildPtr) { return rChildPtr.get() == pBackupData; });
521 if (it != m_RedlineChildren.end())
522 m_RedlineChildren.erase(it);
523
524 pBackupData = pNext;
525 }
526 pParent->pNext = nullptr;
527
528 // insert new children
529 InsertChildren(pParent, rRedln, bHasRedlineAutoFormat);
530
531 rTreeView.thaw();
532 return nStart;
533 }
534
535 // have entries been deleted?
536 const SwRedlineData *pRedlineData = &rRedln.GetRedlineData();
537 for (SwRedlineTable::size_type i = nStart + 1; i < m_RedlineParents.size(); i++)
538 {
539 if (m_RedlineParents[i]->pData == pRedlineData)
540 {
541 // remove entries from nStart to i-1
542 RemoveParents(nStart, i - 1);
543 rTreeView.thaw();
544 return nStart - 1;
545 }
546 }
547
548 // entries been inserted?
550 pRedlineData = m_RedlineParents[nStart]->pData;
551
552 for (SwRedlineTable::size_type i = nStart + 1; i < nCount; i++)
553 {
554 if (&pSh->GetRedline(i).GetRedlineData() == pRedlineData)
555 {
556 rTreeView.thaw();
557 // insert entries from nStart to i-1
558 InsertParents(nStart, i - 1);
559 return nStart - 1;
560 }
561 }
562
563 rTreeView.thaw();
564 Init(nStart); // adjust all entries until the end
566}
567
568void SwRedlineAcceptDlg::InsertChildren(SwRedlineDataParent *pParent, const SwRangeRedline& rRedln, bool bHasRedlineAutoFormat)
569{
570 SwRedlineDataChild *pLastRedlineChild = nullptr;
571 const SwRedlineData *pRedlineData = &rRedln.GetRedlineData();
572 bool bAutoFormatRedline = rRedln.IsAutoFormat();
573
574 weld::TreeView& rTreeView = m_pTable->GetWidget();
575
576 OUString sAction = GetActionText(rRedln);
577 bool bValidParent = m_sFilterAction.isEmpty() || m_sFilterAction == sAction;
578 bValidParent = bValidParent && m_pTable->IsValidEntry(rRedln.GetAuthorString(), rRedln.GetTimeStamp(), rRedln.GetComment());
579 if (bHasRedlineAutoFormat)
580 {
581
582 if (pParent->pData->GetSeqNo())
583 {
584 std::pair<SwRedlineDataParentSortArr::const_iterator,bool> const ret
585 = m_aUsedSeqNo.insert(pParent);
586 if (ret.second) // already there
587 {
588 if (pParent->xTLBParent)
589 {
590 rTreeView.set_text(*(*ret.first)->xTLBParent, m_sAutoFormat, 0);
591 rTreeView.remove(*pParent->xTLBParent);
592 pParent->xTLBParent.reset();
593 }
594 return;
595 }
596 }
597 bValidParent = bValidParent && bAutoFormatRedline;
598 }
599 bool bValidTree = bValidParent;
600
601 for (sal_uInt16 nStack = 1; nStack < rRedln.GetStackCount(); nStack++)
602 {
603 pRedlineData = pRedlineData->Next();
604
605 SwRedlineDataChild* pRedlineChild = new SwRedlineDataChild;
606 pRedlineChild->pChild = pRedlineData;
607 m_RedlineChildren.push_back(std::unique_ptr<SwRedlineDataChild>(pRedlineChild));
608
609 if ( pLastRedlineChild )
610 pLastRedlineChild->pNext = pRedlineChild;
611 else
612 pParent->pNext = pRedlineChild;
613
614 sAction = GetActionText(rRedln, nStack);
615 bool bValidChild = m_sFilterAction.isEmpty() || m_sFilterAction == sAction;
616 bValidChild = bValidChild && m_pTable->IsValidEntry(rRedln.GetAuthorString(nStack), rRedln.GetTimeStamp(nStack), rRedln.GetComment());
617 if (bHasRedlineAutoFormat)
618 bValidChild = bValidChild && bAutoFormatRedline;
619 bValidTree |= bValidChild;
620
621 if (bValidChild)
622 {
623 std::unique_ptr<RedlinData> pData(new RedlinData);
624 pData->pData = pRedlineChild;
625 pData->bDisabled = true;
626
627 OUString sImage(GetActionImage(rRedln, nStack));
628 OUString sAuthor = rRedln.GetAuthorString(nStack);
629 pData->aDateTime = rRedln.GetTimeStamp(nStack);
630 pData->eType = rRedln.GetType(nStack);
631 OUString sDateEntry = GetAppLangDateTimeString(pData->aDateTime);
632 OUString sComment = rRedln.GetComment(nStack);
633
634 std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator());
635 OUString sId(weld::toId(pData.get()));
636 rTreeView.insert(pParent->xTLBParent.get(), -1, nullptr, &sId, nullptr, nullptr,
637 false, xChild.get());
638 m_RedlinData.push_back(std::move(pData));
639
640 rTreeView.set_image(*xChild, sImage, -1);
641 rTreeView.set_text(*xChild, sAuthor, 1);
642 rTreeView.set_text(*xChild, sDateEntry, 2);
643 rTreeView.set_text(*xChild, sComment, 3);
644
645 pRedlineChild->xTLBChild = std::move(xChild);
646 if (!bValidParent)
647 rTreeView.expand_row(*pParent->xTLBParent);
648 }
649 else
650 pRedlineChild->xTLBChild.reset();
651
652 pLastRedlineChild = pRedlineChild;
653 }
654
655 if (pLastRedlineChild)
656 pLastRedlineChild->pNext = nullptr;
657
658 if (!bValidTree && pParent->xTLBParent)
659 {
660 rTreeView.remove(*pParent->xTLBParent);
661 pParent->xTLBParent.reset();
662 if (bHasRedlineAutoFormat)
663 m_aUsedSeqNo.erase(pParent);
664 }
665}
666
668{
669 SwView *pView = ::GetActiveView();
670 if (!pView)
671 return;
672
673 SwWrtShell* pSh = pView->GetWrtShellPtr();
674 if (!pSh)
675 return;
676
678
679 std::vector<const weld::TreeIter*> aLBoxArr;
680
681 weld::TreeView& rTreeView = m_pTable->GetWidget();
682
683 // because of Bug of TLB that ALWAYS calls the SelectHandler at Remove:
685
686 bool bChildrenRemoved = false;
687 rTreeView.thaw();
688 rTreeView.unselect_all();
689
690 // set the cursor after the last entry because otherwise performance problem in TLB.
691 // TLB would otherwise reset the cursor at every Remove (expensive)
693 weld::TreeIter *pCurEntry = nullptr;
694 while( ( pCurEntry == nullptr ) && ( nPos > 0 ) )
695 {
696 --nPos;
697 pCurEntry = m_RedlineParents[nPos]->xTLBParent.get();
698 }
699
700 if (pCurEntry)
701 rTreeView.set_cursor(*pCurEntry);
702
703 rTreeView.freeze();
704
705 for (SwRedlineTable::size_type i = nStart; i <= nEnd; i++)
706 {
707 if (!bChildrenRemoved && m_RedlineParents[i]->pNext)
708 {
709 SwRedlineDataChild * pChildPtr =
710 const_cast<SwRedlineDataChild*>(m_RedlineParents[i]->pNext);
711 auto it = std::find_if(m_RedlineChildren.begin(), m_RedlineChildren.end(),
712 [&pChildPtr](const std::unique_ptr<SwRedlineDataChild>& rChildPtr) { return rChildPtr.get() == pChildPtr; });
713 if (it != m_RedlineChildren.end())
714 {
715 sal_uInt16 nChildren = 0;
716 while (pChildPtr)
717 {
718 pChildPtr = const_cast<SwRedlineDataChild*>(pChildPtr->pNext);
719 nChildren++;
720 }
721
722 m_RedlineChildren.erase(it, it + nChildren);
723 bChildrenRemoved = true;
724 }
725 }
726 weld::TreeIter *const pEntry = m_RedlineParents[i]->xTLBParent.get();
727 if (pEntry)
728 aLBoxArr.push_back(pEntry);
729 }
730
731 std::sort(aLBoxArr.begin(), aLBoxArr.end(), [&rTreeView](const weld::TreeIter* a, const weld::TreeIter* b) {
732 return rTreeView.iter_compare(*a, *b) == -1;
733 });
734 // clear TLB from behind
735 for (auto it = aLBoxArr.rbegin(); it != aLBoxArr.rend(); ++it)
736 {
737 const weld::TreeIter* pIter = *it;
738 rTreeView.remove(*pIter);
739 }
740
741 rTreeView.thaw();
742 rTreeView.connect_changed(LINK(this, SwRedlineAcceptDlg, SelectHdl));
743 // unfortunately by Remove it was selected from the TLB always again ...
744 rTreeView.unselect_all();
745 rTreeView.freeze();
746
747 m_RedlineParents.erase(m_RedlineParents.begin() + nStart, m_RedlineParents.begin() + nEnd + 1);
748}
749
751{
752 SwView *pView = ::GetActiveView();
753 if (!pView)
754 return;
755
756 SwWrtShell* pSh = pView->GetWrtShellPtr();
757 if (!pSh)
758 return;
759
760 bool bHasRedlineAutoFormat = HasRedlineAutoFormat();
761
763 nEnd = std::min(nEnd, (nCount - 1)); // also treats nEnd=SwRedlineTable::npos (until the end)
764
765 if (nEnd == SwRedlineTable::npos)
766 return; // no redlines in the document
767
768 weld::TreeView& rTreeView = m_pTable->GetWidget();
769
770 SwRedlineDataParent* pRedlineParent;
771 const SwRangeRedline* pCurrRedline;
772 if (!nStart && !rTreeView.get_selected(nullptr))
773 {
774 pCurrRedline = pSh->GetCurrRedline();
775 if( !pCurrRedline )
776 {
777 pSh->SwCursorShell::Push();
778 pCurrRedline = pSh->SelNextRedline();
779 if( nullptr == pCurrRedline )
780 pCurrRedline = pSh->SelPrevRedline();
781 pSh->SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
782 }
783 }
784 else
785 pCurrRedline = nullptr;
786
787 rTreeView.freeze();
788 if (m_pTable->IsSorted())
789 rTreeView.make_unsorted();
790
791 bool bIsShowChangesInMargin = SW_MOD()->GetUsrPref(false)->IsShowChangesInMargin();
792
793 // collect redlines of tracked table or table row insertion/deletions under a single tree list
794 // item to accept/reject table (row) insertion/deletion with a single click on Accept/Reject
795 // Note: because update of the tree list depends on parent count, we don't modify
796 // m_RedlineParents, only store the 2nd and more redlines as children of the tree list
797 // item of the first redline
798
799 // count of items stored as children (to adjust parent position)
800 sal_Int32 nSkipRedlines = 0;
801 // count of items of the actual table row (or joined table rows) stored as children =
802 // redlines of the row(s) - 1 (first redline is associated to the parent tree list item)
803 sal_Int32 nSkipRedline = 0;
804 // nSkipRedline of the previous table row (to join multiple table rows, if it's possible)
805 sal_Int32 nPrevSkipRedline = 0;
806
807 // last SwRangeRedline in the table row
809 // descriptor redline of the tracked table row
811 // descriptor redline of the previous table row to join the table rows
813
814 // show all redlines as tree list items,
815 // redlines of a tracked table (row) insertion/deletion showed as children of a single parent
816 for (SwRedlineTable::size_type i = nStart; i <= nEnd; i++)
817 {
818 const SwRangeRedline& rRedln = pSh->GetRedline(i);
819 const SwRedlineData *pRedlineData = &rRedln.GetRedlineData();
820
821 pRedlineParent = new SwRedlineDataParent;
822 pRedlineParent->pData = pRedlineData;
823 pRedlineParent->pNext = nullptr;
824
825 // handle tracked table row changes
826 const SwTableBox* pTableBox;
827 const SwTableLine* pTableLine;
828 // first SwRangeRedline of the tracked table row(s), base of the parent tree list
829 // of the other SwRangeRedlines of the tracked table row(s)
831 if ( // not recognized yet as tracked table row change
832 nLastChangeInRow == SwRedlineTable::npos &&
833 nullptr != ( pTableBox = pSh->GetRedline(i).Start()->GetNode().GetTableBox() ) &&
834 nullptr != ( pTableLine = pTableBox->GetUpper() ) &&
835 // it's a tracked row change based on the cached row data
836 RedlineType::None != pTableLine->GetRedlineType() )
837 {
838 SwRedlineTable::size_type nRedline = i;
839 nRowChange = pTableLine->UpdateTextChangesOnly(nRedline);
840 if ( SwRedlineTable::npos != nRowChange )
841 {
842 nSkipRedline = nRedline - i - 1;
843 nLastChangeInRow = nRedline - 1;
844 // join the consecutive deleted/inserted rows under a single treebox item,
845 // if they have the same redline data (equal type, author and time stamp)
846 if ( nPrevRowChange != SwRedlineTable::npos &&
847 pSh->GetRedline(nRowChange).GetRedlineData() == pSh->GetRedline(nPrevRowChange).GetRedlineData() )
848 {
849 nSkipRedline += nPrevSkipRedline + 1;
850 nPrevSkipRedline = 0;
851 nPrevRowChange = SwRedlineTable::npos;
852 }
853 else
854 nNewTableParent = i;
855 }
856 else
857 nPrevRowChange = SwRedlineTable::npos;
858 }
859 else
860 nPrevRowChange = SwRedlineTable::npos;
861
862 bool bRowChange(SwRedlineTable::npos != nLastChangeInRow);
863
864 bool bShowDeletedTextAsComment = bIsShowChangesInMargin &&
865 RedlineType::Delete == rRedln.GetType() && rRedln.GetComment().isEmpty();
866 const OUString& sComment = bShowDeletedTextAsComment
867 ? const_cast<SwRangeRedline&>(rRedln).GetDescr()
868 : rRedln.GetComment();
869 pRedlineParent->sComment = sComment.replace('\n', ' ');
870 m_RedlineParents.insert(m_RedlineParents.begin() + i,
871 std::unique_ptr<SwRedlineDataParent>(pRedlineParent));
872
873 std::unique_ptr<RedlinData> pData(new RedlinData);
874 pData->pData = pRedlineParent;
875 pData->bDisabled = false;
876
877 // use descriptor SwRangeRedline of the changed row, if needed to show
878 // the correct redline type, author and time stamp of the tracked row change
879 const SwRangeRedline& rChangeRedln = pSh->GetRedline(bRowChange ? nRowChange : i);
880
881 OUString sImage = GetActionImage(rChangeRedln, 0, bRowChange && nNewTableParent != SwRedlineTable::npos );
882 OUString sAuthor = rChangeRedln.GetAuthorString(0);
883 pData->aDateTime = rChangeRedln.GetTimeStamp(0);
884 pData->eType = rChangeRedln.GetType(0);
885 OUString sDateEntry = GetAppLangDateTimeString(pData->aDateTime);
886
887 OUString sId = weld::toId(pData.get());
888 std::unique_ptr<weld::TreeIter> xParent(rTreeView.make_iterator());
889
890 if ( !bRowChange || nNewTableParent != SwRedlineTable::npos )
891 rTreeView.insert(nullptr, i - nSkipRedlines, nullptr, &sId, nullptr, nullptr, false, xParent.get());
892 else
893 {
894 // put 2nd or more redlines of deleted/inserted rows as children of their first redline
895 SwRedlineDataParent *const pParent = m_RedlineParents[nLastChangeInRow - nSkipRedline].get();
896 rTreeView.insert(pParent->xTLBParent.get(), -1, nullptr, &sId, nullptr, nullptr, false, xParent.get());
897 }
898
899 m_RedlinData.push_back(std::move(pData));
900
901 rTreeView.set_image(*xParent, sImage, -1);
902 rTreeView.set_text(*xParent, sAuthor, 1);
903 rTreeView.set_text(*xParent, sDateEntry, 2);
904 rTreeView.set_text(*xParent, sComment, 3);
905
906 if (pCurrRedline == &rRedln)
907 {
908 rTreeView.thaw();
909 rTreeView.set_cursor(*xParent);
910 rTreeView.select(*xParent);
911 rTreeView.scroll_to_row(*xParent);
912 rTreeView.freeze();
913 }
914
915 pRedlineParent->xTLBParent = std::move(xParent);
916
917 InsertChildren(pRedlineParent, rRedln, bHasRedlineAutoFormat);
918
919 // end of a tracked deletion/insertion of a table row
920 if ( nLastChangeInRow != SwRedlineTable::npos && i == nLastChangeInRow )
921 {
922 nSkipRedlines += nSkipRedline;
923 nPrevSkipRedline = nSkipRedline;
924 nSkipRedline = 0;
925 nPrevRowChange = nRowChange;
926 nNewTableParent = SwRedlineTable::npos;
927 nLastChangeInRow = SwRedlineTable::npos;
928 }
929 }
930 rTreeView.thaw();
931 if (m_pTable->IsSorted())
932 rTreeView.make_sorted();
933}
934
935void SwRedlineAcceptDlg::CallAcceptReject( bool bSelect, bool bAccept )
936{
937 SwView *pView = ::GetActiveView();
938 if (!pView)
939 return;
940
941 SwWrtShell* pSh = pView->GetWrtShellPtr();
942 if (!pSh)
943 return;
944
945 int nPos = -1;
946
947 typedef std::vector<std::unique_ptr<weld::TreeIter>> ListBoxEntries_t;
948 ListBoxEntries_t aRedlines;
949
950 // don't activate
951 OSL_ENSURE( !m_bInhibitActivate,
952 "recursive call of CallAcceptReject?");
953 m_bInhibitActivate = true;
954
955 weld::TreeView& rTreeView = m_pTable->GetWidget();
956
957 auto lambda = [this, pSh, bSelect, bAccept, &rTreeView, &nPos, &aRedlines](weld::TreeIter& rEntry) {
958 if (!rTreeView.get_iter_depth(rEntry))
959 {
960 if (bSelect && nPos == -1)
961 nPos = rTreeView.get_iter_index_in_parent(rEntry);
962
963 RedlinData *pData = weld::fromId<RedlinData*>(rTreeView.get_id(rEntry));
964
965 bool bIsNotFormatted = true;
966
967 // first remove only changes with insertion/deletion, if they exist
968 // (format-only changes haven't had real rejection yet, only an
969 // approximation: clear direct formatting, so try to warn
970 // with the extended button label "Reject All/Clear formatting")
971 if ( !bSelect && !bAccept && !m_bOnlyFormatedRedlines )
972 {
973 SwRedlineTable::size_type nPosition = GetRedlinePos(rEntry);
974 const SwRangeRedline& rRedln = pSh->GetRedline(nPosition);
975
976 if( RedlineType::Format == rRedln.GetType() )
977 bIsNotFormatted = false;
978 }
979
980 if (!pData->bDisabled && bIsNotFormatted)
981 aRedlines.emplace_back(rTreeView.make_iterator(&rEntry));
982 }
983 return false;
984 };
985
986 // collect redlines-to-be-accepted/rejected in aRedlines vector
987 if (bSelect)
988 rTreeView.selected_foreach(lambda);
989 else
990 rTreeView.all_foreach(lambda);
991
993 if( !bAccept )
994 FnAccRej = &SwEditShell::RejectRedline;
995
996 SwWait aWait( *pSh->GetView().GetDocShell(), true );
997 pSh->StartAction();
998
999 bool bMoreRedlines( aRedlines.size() > 1 ||
1000 // single item with children, e.g. multiple redlines of a table or table row deletion/insertion
1001 ( aRedlines.size() == 1 && rTreeView.iter_n_children(*aRedlines[0]) > 0 ) );
1002
1003 // don't add extra Undo label to a single item only with redline stack (i.e. old changes
1004 // on the same text range, stored only in OOXML)
1005 if ( bMoreRedlines && aRedlines.size() == 1 )
1006 {
1007 std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator( &*aRedlines[0] ));
1008 RedlinData *pData = weld::fromId<RedlinData*>(rTreeView.get_id(*xChild));
1009 if ( pData->bDisabled )
1010 bMoreRedlines = false;
1011 }
1012
1013 if ( bMoreRedlines )
1014 {
1015 OUString aTmpStr;
1016 {
1017 SwRewriter aRewriter;
1018 aRewriter.AddRule(UndoArg1,
1019 OUString::number(aRedlines.size()));
1020 aTmpStr = aRewriter.Apply(SwResId(STR_N_REDLINES));
1021 }
1022
1023 SwRewriter aRewriter;
1024 aRewriter.AddRule(UndoArg1, aTmpStr);
1025
1027 &aRewriter);
1028 }
1029
1030 // accept/reject the redlines in aRedlines. The absolute
1031 // position may change during the process (e.g. when two redlines
1032 // are merged in result of another one being deleted), so the
1033 // position must be resolved late and checked before using it.
1034 // (cf #102547#)
1035 for (const auto& rRedLine : aRedlines)
1036 {
1037 SwRedlineTable::size_type nPosition = GetRedlinePos( *rRedLine );
1038 if( nPosition != SwRedlineTable::npos )
1039 (pSh->*FnAccRej)( nPosition );
1040
1041 // handle redlines of table rows, stored as children of the item associated
1042 // to the deleted/inserted table row(s)
1043 std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator( &*rRedLine ));
1044 if ( rTreeView.iter_children(*xChild) )
1045 {
1046 RedlinData *pData = weld::fromId<RedlinData*>(rTreeView.get_id(*xChild));
1047 // disabled for redline stack, but not for redlines of table rows
1048 if ( !pData->bDisabled )
1049 {
1050 do
1051 {
1052 nPosition = GetRedlinePos( *xChild );
1053 if( nPosition != SwRedlineTable::npos )
1054 (pSh->*FnAccRej)( nPosition );
1055 }
1056 while ( rTreeView.iter_next_sibling(*xChild) );
1057 }
1058 }
1059 }
1060
1061 if ( bMoreRedlines )
1062 {
1063 pSh->EndUndo();
1064 }
1065
1066 pSh->EndAction();
1067
1068 m_bInhibitActivate = false;
1069 Activate();
1070
1071 if (nPos != -1 && rTreeView.n_children())
1072 {
1073 if (nPos >= rTreeView.n_children())
1074 nPos = rTreeView.n_children() - 1;
1075 rTreeView.select(nPos);
1076 rTreeView.scroll_to_row(nPos);
1077 rTreeView.set_cursor(nPos);
1078 SelectHdl(rTreeView);
1079 }
1081}
1082
1084{
1085 SwView* pView = GetActiveView();
1086 if (!pView)
1087 return SwRedlineTable::npos;
1088
1089 SwWrtShell* pSh = pView->GetWrtShellPtr();
1090 if (!pSh)
1091 return SwRedlineTable::npos;
1092
1093 weld::TreeView& rTreeView = m_pTable->GetWidget();
1094 return pSh->FindRedlineOfData( *static_cast<SwRedlineDataParent*>(weld::fromId<RedlinData*>(
1095 rTreeView.get_id(rEntry))->pData)->pData );
1096}
1097
1099{
1100 CallAcceptReject( true, true );
1101}
1102
1104{
1105 CallAcceptReject( false, true );
1106}
1107
1109{
1110 CallAcceptReject( true, false );
1111}
1112
1114{
1115 CallAcceptReject( false, false );
1116}
1117
1119{
1120 if (SwView* pView = GetActiveView())
1121 {
1122 pView->GetViewFrame().GetDispatcher()->
1123 Execute(SID_UNDO, SfxCallMode::SYNCHRON);
1124 m_pTPView->EnableUndo(pView->GetSlotState(SID_UNDO) != nullptr);
1125 }
1126
1127 Activate();
1128}
1129
1131{
1132 SvxTPFilter *pFilterTP = m_xTabPagesCTRL->GetFilterPage();
1133
1134 if (pFilterTP->IsAction())
1135 m_sFilterAction = pFilterTP->GetLbAction()->get_active_text();
1136 else
1137 m_sFilterAction.clear();
1138
1139 Init();
1140}
1141
1143{
1144 m_aSelectTimer.Start();
1145}
1146
1148{
1149 m_aSelectTimer.Stop();
1150
1151 SwView* pView = GetActiveView();
1152 if (!pView)
1153 return;
1154
1155 SwWrtShell* pSh = pView->GetWrtShellPtr();
1156 if (!pSh)
1157 return;
1158
1159 bool bIsNotFormated = false;
1160 bool bSel = false;
1161
1162 //#98883# don't select redlines while the dialog is not focused
1163 //#107938# But not only ask pTable if it has the focus. To move
1164 // the selection to the selected redline any child of pParentDlg
1165 // may the focus.
1166 if (!m_xParentDlg || m_xParentDlg->has_toplevel_focus())
1167 {
1168 weld::TreeView& rTreeView = m_pTable->GetWidget();
1169 std::unique_ptr<weld::TreeIter> xActEntry(rTreeView.make_iterator());
1170 if (rTreeView.get_selected(xActEntry.get()))
1171 {
1172 pSh->StartAction();
1173 pSh->EnterStdMode();
1174 SwViewShell::SetCareDialog(m_xParentDlg);
1175
1176 rTreeView.selected_foreach([this, pSh, &rTreeView, &xActEntry, &bIsNotFormated, &bSel](weld::TreeIter& rEntry){
1177 rTreeView.copy_iterator(rEntry, *xActEntry);
1178 if (rTreeView.get_iter_depth(rEntry))
1179 {
1180 rTreeView.iter_parent(*xActEntry);
1181 if (rTreeView.is_selected(*xActEntry))
1182 return false; // don't select twice
1183 }
1184 else
1185 bSel = true;
1186
1187 // #98864# find the selected redline (ignore, if the redline is already gone)
1188 SwRedlineTable::size_type nPos = GetRedlinePos(*xActEntry);
1190 {
1191
1192 const SwRangeRedline& rRedln = pSh->GetRedline( nPos );
1193 bIsNotFormated |= RedlineType::Format != rRedln.GetType();
1194
1195 if (pSh->GotoRedline(nPos, true))
1196 {
1197 pSh->SetInSelect();
1198 pSh->EnterAddMode();
1199 }
1200 }
1201
1202 // select all redlines of tracked table rows
1203 std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator( &*xActEntry ));
1204 if ( rTreeView.iter_children(*xChild) )
1205 {
1206 RedlinData *pData = reinterpret_cast<RedlinData*>(rTreeView.get_id(*xChild).toInt64());
1207 // disabled for redline stack, but not for redlines of table rows
1208 if ( !pData->bDisabled )
1209 {
1210 do
1211 {
1212 nPos = GetRedlinePos(*xChild);
1214 {
1215 const SwRangeRedline& rRedln = pSh->GetRedline( nPos );
1216 bIsNotFormated |= RedlineType::Format != rRedln.GetType();
1217
1218 if (pSh->GotoRedline(nPos, true))
1219 {
1220 pSh->SetInSelect();
1221 pSh->EnterAddMode();
1222 }
1223 }
1224 }
1225 while ( rTreeView.iter_next_sibling(*xChild) );
1226 }
1227 }
1228 return false;
1229 });
1230
1231 pSh->LeaveAddMode();
1232 pSh->EndAction();
1234 }
1235 }
1236
1237 bool const bEnable = !pSh->GetDoc()->GetDocShell()->IsReadOnly()
1238 && !pSh->getIDocumentRedlineAccess().GetRedlinePassword().hasElements();
1239 m_pTPView->EnableAccept( bEnable && bSel /*&& !bReadonlySel*/ );
1240 m_pTPView->EnableReject( bEnable && bSel /*&& !bReadonlySel*/ );
1241 m_pTPView->EnableClearFormat( bEnable && bSel && !bIsNotFormated /*&& !bReadonlySel*/ );
1242 m_pTPView->EnableAcceptAll( bEnable );
1243 m_pTPView->EnableRejectAll( bEnable );
1244 m_pTPView->EnableClearFormatAll( bEnable && m_bOnlyFormatedRedlines );
1245}
1246
1247IMPL_LINK(SwRedlineAcceptDlg, CommandHdl, const CommandEvent&, rCEvt, bool)
1248{
1249 if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
1250 return false;
1251
1252 SwView* pView = GetActiveView();
1253 if (!pView)
1254 return false;
1255
1256 SwWrtShell* pSh = pView->GetWrtShellPtr();
1257 if (!pSh)
1258 return false;
1259
1260 const SwRangeRedline *pRed = nullptr;
1261
1262 weld::TreeView& rTreeView = m_pTable->GetWidget();
1263 std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
1264 bool bEntry = rTreeView.get_selected(xEntry.get());
1265 if (bEntry)
1266 {
1267 std::unique_ptr<weld::TreeIter> xTopEntry(rTreeView.make_iterator(xEntry.get()));
1268
1269 if (rTreeView.get_iter_depth(*xTopEntry))
1270 rTreeView.iter_parent(*xTopEntry);
1271
1272 SwRedlineTable::size_type nPos = GetRedlinePos(*xTopEntry);
1273
1274 // disable commenting for protected areas
1275 if (nPos != SwRedlineTable::npos && (pRed = pSh->GotoRedline(nPos, true)) != nullptr)
1276 {
1277 if( pSh->IsCursorPtAtEnd() )
1278 pSh->SwapPam();
1279 pSh->SetInSelect();
1280 }
1281 }
1282
1283 m_xPopup->set_sensitive("writeredit", bEntry && pRed &&
1284 !rTreeView.get_iter_depth(*xEntry) &&
1285 rTreeView.count_selected_rows() == 1);
1286 m_xPopup->set_sensitive("writersort", rTreeView.n_children() != 0);
1287 int nColumn = rTreeView.get_sort_column();
1288 if (nColumn == -1)
1289 nColumn = 4;
1290 for (sal_Int32 i = 0; i < 5; ++i)
1291 m_xSortMenu->set_active(u"writersort" + OUString::number(i), i == nColumn);
1292
1293 OUString sCommand = m_xPopup->popup_at_rect(&rTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
1294
1295 if (sCommand == "writeredit")
1296 {
1297 if (bEntry)
1298 {
1299 if (rTreeView.get_iter_depth(*xEntry))
1300 rTreeView.iter_parent(*xEntry);
1301
1302 SwRedlineTable::size_type nPos = GetRedlinePos(*xEntry);
1303
1305 return true;
1306
1307 const SwRangeRedline &rRedline = pSh->GetRedline(nPos);
1308
1309 /* enable again once we have redline comments in the margin
1310 sComment = rRedline.GetComment();
1311 if ( !sComment.Len() )
1312 GetActiveView()->GetDocShell()->Broadcast(SwRedlineHint(&rRedline,SWREDLINE_INSERTED));
1313 const_cast<SwRangeRedline&>(rRedline).Broadcast(SwRedlineHint(&rRedline,SWREDLINE_FOCUS));
1314 */
1315
1316 OUString sComment = convertLineEnd(rRedline.GetComment(), GetSystemLineEnd());
1318 ::DialogGetRanges fnGetRange = pFact->GetDialogGetRangesFunc();
1319 SfxItemSet aSet( pSh->GetAttrPool(), fnGetRange() );
1320
1321 aSet.Put(SvxPostItTextItem(sComment, SID_ATTR_POSTIT_TEXT));
1322 aSet.Put(SvxPostItAuthorItem(rRedline.GetAuthorString(), SID_ATTR_POSTIT_AUTHOR));
1323
1325 rRedline.GetRedlineData().GetTimeStamp() ),
1326 SID_ATTR_POSTIT_DATE ));
1327
1328 ScopedVclPtr<AbstractSvxPostItDialog> pDlg(pFact->CreateSvxPostItDialog(&rTreeView, aSet));
1329
1330 pDlg->HideAuthor();
1331
1332 TranslateId pResId;
1333 switch( rRedline.GetType() )
1334 {
1335 case RedlineType::Insert:
1336 pResId = STR_REDLINE_INSERTED;
1337 break;
1338 case RedlineType::Delete:
1339 pResId = STR_REDLINE_DELETED;
1340 break;
1341 case RedlineType::Format:
1342 case RedlineType::ParagraphFormat:
1343 pResId = STR_REDLINE_FORMATTED;
1344 break;
1345 case RedlineType::Table:
1346 pResId = STR_REDLINE_TABLECHG;
1347 break;
1348 default:;//prevent warning
1349 }
1350 OUString sTitle(SwResId(STR_REDLINE_COMMENT));
1351 if (pResId)
1352 sTitle += SwResId(pResId);
1353 pDlg->SetText(sTitle);
1354
1355 SwViewShell::SetCareDialog(pDlg->GetDialog());
1356
1357 if ( pDlg->Execute() == RET_OK )
1358 {
1359 const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
1360 OUString sMsg(pOutSet->Get(SID_ATTR_POSTIT_TEXT).GetValue());
1361
1362 // insert / change comment
1363 pSh->SetRedlineComment(sMsg);
1364 rTreeView.set_text(*xEntry, sMsg.replace('\n', ' '), 3);
1365 Init();
1366 }
1367
1369 pDlg.disposeAndClear();
1370 }
1371 }
1372 else if (!sCommand.isEmpty())
1373 {
1374 int nSortMode = o3tl::toInt32(sCommand.subView(10));
1375
1376 if (nSortMode == 4 && nColumn == 4)
1377 return true; // we already have it
1378 if (nSortMode == 4)
1379 nSortMode = -1; // unsorted / sorted by position
1380
1381 SwWait aWait( *pView->GetDocShell(), false );
1382 m_pTable->HeaderBarClick(nSortMode);
1383 if (nSortMode == -1)
1384 Init(); // newly fill everything
1385 }
1386 return true;
1387}
1388
1389namespace
1390{
1391 OUString lcl_StripAcceptChgDat(OUString &rExtraString)
1392 {
1393 OUString aStr;
1394 while(true)
1395 {
1396 sal_Int32 nPos = rExtraString.indexOf("AcceptChgDat:");
1397 if (nPos == -1)
1398 break;
1399 // try to read the alignment string "ALIGN:(...)"; if none existing,
1400 // it's an old version
1401 sal_Int32 n1 = rExtraString.indexOf('(', nPos);
1402 if (n1 != -1)
1403 {
1404 sal_Int32 n2 = rExtraString.indexOf(')', n1);
1405 if (n2 != -1)
1406 {
1407 // cut out the alignment string
1408 aStr = rExtraString.copy(nPos, n2 - nPos + 1);
1409 rExtraString = rExtraString.replaceAt(nPos, n2 - nPos + 1, u"");
1410 aStr = aStr.copy(n1 - nPos + 1);
1411 }
1412 }
1413 }
1414 return aStr;
1415 }
1416}
1417
1418void SwRedlineAcceptDlg::Initialize(OUString& rExtraString)
1419{
1420 if (rExtraString.isEmpty())
1421 return;
1422
1423 OUString aStr = lcl_StripAcceptChgDat(rExtraString);
1424 if (aStr.isEmpty())
1425 return;
1426
1427 int nCount = aStr.toInt32();
1428 if (nCount <= 2)
1429 return;
1430
1431 std::vector<int> aEndPos;
1432
1433 for (int i = 0; i < nCount; ++i)
1434 {
1435 sal_Int32 n1 = aStr.indexOf(';');
1436 aStr = aStr.copy( n1+1 );
1437 aEndPos.push_back(aStr.toInt32());
1438 }
1439
1440 bool bUseless = false;
1441
1442 std::vector<int> aWidths;
1443 for (int i = 1; i < nCount; ++i)
1444 {
1445 aWidths.push_back(aEndPos[i] - aEndPos[i - 1]);
1446 if (aWidths.back() <= 0)
1447 bUseless = true;
1448 }
1449
1450 if (!bUseless)
1451 {
1452 // turn column end points back to column widths, ignoring the small
1453 // value used for the expander column
1454 weld::TreeView& rTreeView = m_pTable->GetWidget();
1455 rTreeView.set_column_fixed_widths(aWidths);
1456 }
1457}
1458
1459void SwRedlineAcceptDlg::FillInfo(OUString &rExtraData) const
1460{
1461 //remove any old one before adding a new one
1462 lcl_StripAcceptChgDat(rExtraData);
1463 rExtraData += "AcceptChgDat:(";
1464
1465 const int nTabCount = 4;
1466
1467 rExtraData += OUString::number(nTabCount);
1468 rExtraData += ";";
1469
1470 weld::TreeView& rTreeView = m_pTable->GetWidget();
1471 std::vector<int> aWidths;
1472 // turn column widths back into column end points for compatibility
1473 // with how they used to be stored, including a small value for the
1474 // expander column
1475 aWidths.push_back(rTreeView.get_checkbox_column_width());
1476 for (int i = 0; i < nTabCount - 1; ++i)
1477 {
1478 int nWidth = rTreeView.get_column_width(i);
1479 assert(nWidth > 0 && "suspicious to get a value like this");
1480 aWidths.push_back(aWidths.back() + nWidth);
1481 }
1482
1483 for (auto a : aWidths)
1484 {
1485 rExtraData += OUString::number(a);
1486 rExtraData += ";";
1487 }
1488 rExtraData += ")";
1489}
1490
1492 : PanelLayout(pParent, "ManageChangesPanel", "modules/swriter/ui/managechangessidebar.ui")
1493 , mxContentArea(m_xBuilder->weld_container("content_area"))
1494{
1495 mpImplDlg.reset(new SwRedlineAcceptDlg(nullptr, m_xBuilder.get(), mxContentArea.get()));
1496
1497 mpImplDlg->Init();
1498
1499 // we want to receive SfxHintId::DocChanged
1500 StartListening(*(SW_MOD()->GetView()->GetDocShell()));
1501}
1502
1504{
1505}
1506
1508{
1509 if (mpImplDlg && rHint.GetId() == SfxHintId::DocChanged)
1510 mpImplDlg->Activate();
1511}
1512
1513/* 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:1230
void EndAction(const bool bIdleEnd=false)
Definition: crsrsh.cxx:243
const SwRangeRedline * SelNextRedline()
Definition: crstrvl.cxx:2466
const SwRangeRedline * SelPrevRedline()
Definition: crstrvl.cxx:2493
bool IsCursorPtAtEnd() const
Definition: crsrsh.hxx:919
SwDocShell * GetDocShell()
Definition: doc.hxx:1367
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:128
std::unique_ptr< weld::Container > m_xContentArea
Definition: redlndlg.hxx:127
SwChildWinWrapper * m_pChildWin
Definition: redlndlg.hxx:129
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:114
OUString m_sFormated
Definition: redlndlg.hxx:69
void FillInfo(OUString &rExtraData) const
Definition: redlndlg.cxx:1459
OUString m_sFilterAction
Definition: redlndlg.hxx:72
SAL_DLLPRIVATE void InitAuthors()
Definition: redlndlg.cxx:241
OUString m_sInserted
Definition: redlndlg.hxx:67
void Init(SwRedlineTable::size_type nStart=0)
Definition: redlndlg.cxx:211
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:343
SvxTPView * m_pTPView
Definition: redlndlg.hxx:82
OUString m_sAutoFormat
Definition: redlndlg.hxx:73
static SAL_DLLPRIVATE OUString GetActionImage(const SwRangeRedline &rRedln, sal_uInt16 nStack=0, bool bRowChanges=false)
Definition: redlndlg.cxx:315
void Initialize(OUString &rExtraData)
Definition: redlndlg.cxx:1418
SAL_DLLPRIVATE void RemoveParents(SwRedlineTable::size_type nStart, SwRedlineTable::size_type nEnd)
Definition: redlndlg.cxx:667
void CallAcceptReject(bool bSelect, bool bAccept)
Definition: redlndlg.cxx:935
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:568
SAL_DLLPRIVATE SwRedlineTable::size_type GetRedlinePos(const weld::TreeIter &rEntry)
Definition: redlndlg.cxx:1083
std::unique_ptr< SvxAcceptChgCtr > m_xTabPagesCTRL
Definition: redlndlg.hxx:80
SAL_DLLPRIVATE SwRedlineTable::size_type CalcDiff(SwRedlineTable::size_type nStart, bool bChild)
Definition: redlndlg.cxx:485
SwRedlineAcceptDlg(SwRedlineAcceptDlg const &)=delete
SAL_DLLPRIVATE void InsertParents(SwRedlineTable::size_type nStart, SwRedlineTable::size_type nEnd=SwRedlineTable::npos)
Definition: redlndlg.cxx:750
OUString m_sTableChgd
Definition: redlndlg.hxx:70
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:83
std::unique_ptr< SwRedlineAcceptDlg > mpImplDlg
Definition: redlndlg.hxx:156
SwRedlineAcceptPanel(weld::Widget *pParent)
Definition: redlndlg.cxx:1491
std::unique_ptr< weld::Container > mxContentArea
Definition: redlndlg.hxx:157
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:1507
virtual ~SwRedlineAcceptPanel() override
Definition: redlndlg.cxx:1503
sal_uInt16 GetSeqNo() const
Definition: redline.hxx:156
const SwRedlineData * Next() const
Definition: redline.hxx:137
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
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:2653
SwDoc * GetDoc() const
Definition: viewsh.hxx:307
const IDocumentRedlineAccess & getIDocumentRedlineAccess() const
Provides access to the document redline interface.
Definition: viewsh.cxx:2809
const SfxItemPool & GetAttrPool() const
Definition: viewsh.hxx:649
Definition: view.hxx:146
SwWrtShell * GetWrtShellPtr() const
Definition: view.hxx:424
SwDocShell * GetDocShell()
Definition: view.cxx:1180
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:1098
IMPL_LINK(SwRedlineAcceptDlg, CommandHdl, const CommandEvent &, rCEvt, bool)
Definition: redlndlg.cxx:1247
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:256
@ REJECT_REDLINE
@ ACCEPT_REDLINE
OUString GetAppLangDateTimeString(const DateTime &)
Definition: uitool.cxx:862
OUString sId
RET_OK