1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svl/undo.hxx>
21 #include <unotools/textsearch.hxx>
22 #include <unotools/localedatawrapper.hxx>
23 #include <unotools/collatorwrapper.hxx>
24 #include <sfx2/viewfrm.hxx>
25 #include <sfx2/basedlgs.hxx>
26 #include <vcl/commandevent.hxx>
27 #include <o3tl/string_view.hxx>
29 #include <acredlin.hxx>
31 #include <reffact.hxx>
32 #include <document.hxx>
34 #include <scresid.hxx>
35 #include <strings.hrc>
37 #include <tabvwsh.hxx>
39 // defines -------------------------------------------------------------------
41 #define RD_SPECIAL_NONE 0
42 #define RD_SPECIAL_CONTENT 1
43 #define RD_SPECIAL_VISCONTENT 2
46 ScRedlinData::ScRedlinData()
48 nInfo
=RD_SPECIAL_NONE
;
59 ScRedlinData::~ScRedlinData()
61 nInfo
=RD_SPECIAL_NONE
;
70 ScAcceptChgDlg::ScAcceptChgDlg(SfxBindings
* pB
, SfxChildWindow
* pCW
, weld::Window
* pParent
,
71 ScViewData
* ptrViewData
)
72 : SfxModelessDialogController(pB
, pCW
, pParent
,
73 u
"svx/ui/acceptrejectchangesdialog.ui"_ustr
, u
"AcceptRejectChangesDialog"_ustr
)
74 , aSelectionIdle( "ScAcceptChgDlg aSelectionIdle" )
75 , aReOpenIdle("ScAcceptChgDlg ReOpenIdle")
76 , pViewData( ptrViewData
)
77 , pDoc( &ptrViewData
->GetDocument() )
78 , aStrInsertCols(ScResId(STR_CHG_INSERT_COLS
))
79 , aStrInsertRows(ScResId(STR_CHG_INSERT_ROWS
))
80 , aStrInsertTabs(ScResId(STR_CHG_INSERT_TABS
))
81 , aStrDeleteCols(ScResId(STR_CHG_DELETE_COLS
))
82 , aStrDeleteRows(ScResId(STR_CHG_DELETE_ROWS
))
83 , aStrDeleteTabs(ScResId(STR_CHG_DELETE_TABS
))
84 , aStrMove(ScResId(STR_CHG_MOVE
))
85 , aStrContent(ScResId(STR_CHG_CONTENT
))
86 , aStrReject(ScResId(STR_CHG_REJECT
))
87 , aStrAllAccepted(ScResId(STR_CHG_ACCEPTED
))
88 , aStrAllRejected(ScResId(STR_CHG_REJECTED
))
89 , aStrNoEntry(ScResId(STR_CHG_NO_ENTRY
))
90 , aStrContentWithChild(ScResId(STR_CHG_CONTENT_WITH_CHILD
))
91 , aStrChildContent(ScResId(STR_CHG_CHILD_CONTENT
))
92 , aStrChildOrgContent(ScResId(STR_CHG_CHILD_ORGCONTENT
))
93 , aStrEmpty(ScResId(STR_CHG_EMPTY
))
94 , aUnknown(u
"Unknown"_ustr
)
97 , bHasFilterEntry(false)
99 , m_xContentArea(m_xDialog
->weld_content_area())
100 , m_xPopup(m_xBuilder
->weld_menu(u
"calcmenu"_ustr
))
101 , m_xSortMenu(m_xBuilder
->weld_menu(u
"calcsortmenu"_ustr
))
103 m_xAcceptChgCtr
.reset(new SvxAcceptChgCtr(m_xContentArea
.get()));
106 aReOpenIdle
.SetInvokeHandler(LINK( this, ScAcceptChgDlg
, ReOpenTimerHdl
));
108 pTPFilter
= m_xAcceptChgCtr
->GetFilterPage();
109 pTPView
= m_xAcceptChgCtr
->GetViewPage();
111 // tdf#136062 Don't use "Reject/Clear formatting" instead of "Reject" buttons in Calc
112 pTPView
->EnableClearFormat(false);
113 pTPView
->EnableClearFormatAll(false);
115 pTheView
= pTPView
->GetTableControl();
116 pTheView
->SetCalcView();
117 aSelectionIdle
.SetInvokeHandler(LINK( this, ScAcceptChgDlg
, UpdateSelectionHdl
));
119 pTPFilter
->SetReadyHdl(LINK( this, ScAcceptChgDlg
, FilterHandle
));
120 pTPFilter
->SetRefHdl(LINK( this, ScAcceptChgDlg
, RefHandle
));
121 pTPFilter
->HideRange(false);
122 pTPView
->SetRejectClickHdl( LINK( this, ScAcceptChgDlg
,RejectHandle
));
123 pTPView
->SetAcceptClickHdl( LINK(this, ScAcceptChgDlg
, AcceptHandle
));
124 pTPView
->SetRejectAllClickHdl( LINK( this, ScAcceptChgDlg
,RejectAllHandle
));
125 pTPView
->SetAcceptAllClickHdl( LINK(this, ScAcceptChgDlg
, AcceptAllHandle
));
127 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
128 rTreeView
.connect_expanding(LINK(this, ScAcceptChgDlg
, ExpandingHandle
));
129 rTreeView
.connect_selection_changed(LINK(this, ScAcceptChgDlg
, SelectHandle
));
130 rTreeView
.connect_popup_menu(LINK(this, ScAcceptChgDlg
, CommandHdl
));
131 rTreeView
.set_sort_func([this](const weld::TreeIter
& rLeft
, const weld::TreeIter
& rRight
){
132 return ColCompareHdl(rLeft
, rRight
);
134 rTreeView
.set_selection_mode(SelectionMode::Multiple
);
140 std::unique_ptr
<weld::TreeIter
> xEntry(rTreeView
.make_iterator());
141 if (rTreeView
.get_iter_first(*xEntry
))
142 rTreeView
.select(*xEntry
);
145 ScAcceptChgDlg::~ScAcceptChgDlg()
148 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
152 Link
<ScChangeTrack
&,void> aLink
;
153 pChanges
->SetModifiedLink(aLink
);
157 void ScAcceptChgDlg::ReInit(ScViewData
* ptrViewData
)
159 pViewData
=ptrViewData
;
161 pDoc
= &ptrViewData
->GetDocument();
170 // don't call Init here (switching between views), just set link below
171 // (dialog is just hidden, not deleted anymore, when switching views)
177 ScChangeTrack
* pChanges
= pDoc
->GetChangeTrack();
179 pChanges
->SetModifiedLink( LINK( this, ScAcceptChgDlg
, ChgTrackModHdl
) );
183 void ScAcceptChgDlg::Init()
185 OSL_ENSURE( pViewData
&& pDoc
, "ViewData or Document not found!" );
187 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
189 if(pChanges
!=nullptr)
191 pChanges
->SetModifiedLink( LINK( this, ScAcceptChgDlg
,ChgTrackModHdl
));
192 aChangeViewSet
.SetTheAuthorToShow(pChanges
->GetUser());
193 pTPFilter
->ClearAuthors();
194 const std::set
<OUString
>& rUserColl
= pChanges
->GetUserCollection();
195 for (const auto& rItem
: rUserColl
)
196 pTPFilter
->InsertAuthor(rItem
);
199 ScChangeViewSettings
* pViewSettings
=pDoc
->GetChangeViewSettings();
200 if ( pViewSettings
!=nullptr )
201 aChangeViewSet
= *pViewSettings
;
202 // adjust TimeField for filter tabpage
203 aChangeViewSet
.AdjustDateMode( *pDoc
);
205 pTPFilter
->CheckDate(aChangeViewSet
.HasDate());
207 DateTime
aEmpty(DateTime::EMPTY
);
209 DateTime
aDateTime(aChangeViewSet
.GetTheFirstDateTime());
210 if (aDateTime
!= aEmpty
)
212 pTPFilter
->SetFirstDate(aDateTime
);
213 pTPFilter
->SetFirstTime(aDateTime
);
215 aDateTime
= aChangeViewSet
.GetTheLastDateTime();
216 if (aDateTime
!= aEmpty
)
218 pTPFilter
->SetLastDate(aDateTime
);
219 pTPFilter
->SetLastTime(aDateTime
);
222 pTPFilter
->SetDateMode(static_cast<sal_uInt16
>(aChangeViewSet
.GetTheDateMode()));
223 pTPFilter
->CheckComment(aChangeViewSet
.HasComment());
224 pTPFilter
->SetComment(aChangeViewSet
.GetTheComment());
226 pTPFilter
->CheckAuthor(aChangeViewSet
.HasAuthor());
227 OUString aString
=aChangeViewSet
.GetTheAuthorToShow();
228 if(!aString
.isEmpty())
230 pTPFilter
->SelectAuthor(aString
);
231 if(pTPFilter
->GetSelectedAuthor()!=aString
)
233 pTPFilter
->InsertAuthor(aString
);
234 pTPFilter
->SelectAuthor(aString
);
238 pTPFilter
->SelectedAuthorPos(0);
240 pTPFilter
->CheckRange(aChangeViewSet
.HasRange());
242 aRangeList
=aChangeViewSet
.GetTheRangeList();
244 if( !aChangeViewSet
.GetTheRangeList().empty() )
246 const ScRange
& rRangeEntry
= aChangeViewSet
.GetTheRangeList().front();
247 OUString
aRefStr(rRangeEntry
.Format(*pDoc
, ScRefFlags::RANGE_ABS_3D
));
248 pTPFilter
->SetRange(aRefStr
);
252 if(!(pTPFilter
->IsDate()||pTPFilter
->IsRange()||
253 pTPFilter
->IsAuthor()||pTPFilter
->IsComment()))
256 pTheView
->SetFilterDate(pTPFilter
->IsDate());
257 pTheView
->SetDateTimeMode(pTPFilter
->GetDateMode());
258 pTheView
->SetFirstDate(pTPFilter
->GetFirstDate());
259 pTheView
->SetLastDate(pTPFilter
->GetLastDate());
260 pTheView
->SetFirstTime(pTPFilter
->GetFirstTime());
261 pTheView
->SetLastTime(pTPFilter
->GetLastTime());
262 pTheView
->SetFilterAuthor(pTPFilter
->IsAuthor());
263 pTheView
->SetAuthor(pTPFilter
->GetSelectedAuthor());
265 pTheView
->SetFilterComment(pTPFilter
->IsComment());
267 utl::SearchParam
aSearchParam( pTPFilter
->GetComment(),
268 utl::SearchParam::SearchType::Regexp
,false );
270 pTheView
->SetCommentParams(&aSearchParam
);
272 pTheView
->UpdateFilterTest();
275 void ScAcceptChgDlg::ClearView()
279 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
280 rTreeView
.all_foreach(
281 [&rTreeView
](weld::TreeIter
& rEntry
)
283 ScRedlinData
*pEntryData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(rEntry
));
292 OUString
* ScAcceptChgDlg::MakeTypeString(ScChangeActionType eType
)
299 case SC_CAT_INSERT_COLS
: pStr
=&aStrInsertCols
;break;
300 case SC_CAT_INSERT_ROWS
: pStr
=&aStrInsertRows
;break;
301 case SC_CAT_INSERT_TABS
: pStr
=&aStrInsertTabs
;break;
302 case SC_CAT_DELETE_COLS
: pStr
=&aStrDeleteCols
;break;
303 case SC_CAT_DELETE_ROWS
: pStr
=&aStrDeleteRows
;break;
304 case SC_CAT_DELETE_TABS
: pStr
=&aStrDeleteTabs
;break;
305 case SC_CAT_MOVE
: pStr
=&aStrMove
;break;
306 case SC_CAT_CONTENT
: pStr
=&aStrContent
;break;
307 case SC_CAT_REJECT
: pStr
=&aStrReject
;break;
308 default: pStr
=&aUnknown
;break;
313 bool ScAcceptChgDlg::IsValidAction(const ScChangeAction
* pScChangeAction
)
315 if(pScChangeAction
==nullptr) return false;
319 ScRange aRef
=pScChangeAction
->GetBigRange().MakeRange(*pDoc
);
320 const OUString
& aUser
=pScChangeAction
->GetUser();
321 DateTime aDateTime
=pScChangeAction
->GetDateTime();
323 ScChangeActionType eType
=pScChangeAction
->GetType();
326 OUString aComment
= pScChangeAction
->GetComment().replaceAll("\n", "");
328 if(eType
==SC_CAT_CONTENT
)
330 if(!pScChangeAction
->IsDialogParent())
331 aDesc
= pScChangeAction
->GetDescription(*pDoc
, true);
334 aDesc
= pScChangeAction
->GetDescription(*pDoc
, !pScChangeAction
->IsMasterDelete());
336 if (!aDesc
.isEmpty())
338 aComment
+= " (" + aDesc
+ ")";
341 if (pTheView
->IsValidEntry(aUser
, aDateTime
, aComment
))
343 if(pTPFilter
->IsRange())
345 for ( size_t i
= 0, nRanges
= aRangeList
.size(); i
< nRanges
; ++i
)
347 ScRange
const & rRangeEntry
= aRangeList
[ i
];
348 if (rRangeEntry
.Intersects(aRef
)) {
361 std::unique_ptr
<weld::TreeIter
> ScAcceptChgDlg::AppendChangeAction(
362 const ScChangeAction
* pScChangeAction
, bool bCreateOnDemand
,
363 const weld::TreeIter
* pParent
, bool bDelMaster
, bool bDisabled
)
365 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
367 if(pScChangeAction
==nullptr || pChanges
==nullptr) return nullptr;
371 ScRange aRef
=pScChangeAction
->GetBigRange().MakeRange(*pDoc
);
372 DateTime aDateTime
=pScChangeAction
->GetDateTime();
374 ScChangeActionType eType
=pScChangeAction
->GetType();
375 OUString aActionString
;
381 std::unique_ptr
<ScRedlinData
> pNewData(new ScRedlinData
);
382 pNewData
->pData
=const_cast<ScChangeAction
*>(pScChangeAction
);
383 pNewData
->nActionNo
=pScChangeAction
->GetActionNumber();
384 pNewData
->bIsAcceptable
=pScChangeAction
->IsClickable();
385 pNewData
->bIsRejectable
=pScChangeAction
->IsRejectable();
386 pNewData
->bDisabled
=!pNewData
->bIsAcceptable
|| bDisabled
;
387 pNewData
->aDateTime
=aDateTime
;
388 pNewData
->nRow
= aRef
.aStart
.Row();
389 pNewData
->nCol
= aRef
.aStart
.Col();
390 pNewData
->nTable
= aRef
.aStart
.Tab();
392 if(eType
==SC_CAT_CONTENT
)
394 if(pScChangeAction
->IsDialogParent())
396 aActionString
= aStrContentWithChild
;
397 pNewData
->nInfo
=RD_SPECIAL_VISCONTENT
;
398 pNewData
->bIsRejectable
=false;
399 pNewData
->bIsAcceptable
=false;
403 aActionString
= *MakeTypeString(eType
);
404 aDesc
= pScChangeAction
->GetDescription(*pDoc
, true);
409 aActionString
= *MakeTypeString(eType
);
413 aDesc
= pScChangeAction
->GetDescription(*pDoc
,true);
414 pNewData
->bDisabled
=true;
415 pNewData
->bIsRejectable
=false;
418 aDesc
= pScChangeAction
->GetDescription(*pDoc
, !pScChangeAction
->IsMasterDelete());
422 aRefStr
= pScChangeAction
->GetRefString(*pDoc
, true);
424 bool bIsGenerated
= false;
426 if(!pChanges
->IsGenerated(pScChangeAction
->GetActionNumber()))
428 aUser
= pScChangeAction
->GetUser();
429 aDate
= ScGlobal::getLocaleData().getDate(aDateTime
) + " " + ScGlobal::getLocaleData().getTime(aDateTime
);
430 bIsGenerated
= false;
437 OUString aComment
= pScChangeAction
->GetComment().replaceAll("\n", "");
439 if (!aDesc
.isEmpty())
441 aComment
+= " (" + aDesc
+ ")";
444 if (pTheView
->IsValidEntry(aUser
, aDateTime
) || bIsGenerated
)
446 if (pTheView
->IsValidComment(aComment
))
448 if(pTPFilter
->IsRange())
450 for ( size_t i
= 0, nRanges
= aRangeList
.size(); i
< nRanges
; ++i
)
452 ScRange
const & rRangeEntry
= aRangeList
[ i
];
453 if( rRangeEntry
.Intersects(aRef
) )
455 bHasFilterEntry
=true;
461 else if(!bIsGenerated
)
463 bHasFilterEntry
=true;
469 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
470 std::unique_ptr
<weld::TreeIter
> xEntry(rTreeView
.make_iterator());
471 OUString
sId(weld::toId(pNewData
.release()));
472 rTreeView
.insert(pParent
, -1, &aActionString
, &sId
, nullptr, nullptr, bCreateOnDemand
, xEntry
.get());
473 rTreeView
.set_text( *xEntry
, aRefStr
, 1);
474 if (!aUser
.isEmpty())
475 rTreeView
.set_text( *xEntry
, aUser
, 2);
476 if (!aDate
.isEmpty())
477 rTreeView
.set_text( *xEntry
, aDate
, 3);
478 if (!aComment
.isEmpty())
479 rTreeView
.set_text( *xEntry
, aComment
, 4);
480 if (!bFlag
&& bUseColor
&& !pParent
)
482 rTreeView
.set_font_color(*xEntry
, COL_LIGHTBLUE
);
484 else if (bFlag
&& bUseColor
&& pParent
)
486 rTreeView
.set_font_color(*xEntry
, COL_GREEN
);
488 std::unique_ptr
<weld::TreeIter
> xExpEntry(rTreeView
.make_iterator(pParent
));
490 while (!rTreeView
.get_row_expanded(*xExpEntry
))
492 if (rTreeView
.get_iter_depth(*xExpEntry
))
493 rTreeView
.expand_row(*xExpEntry
);
495 if (!rTreeView
.iter_parent(*xExpEntry
))
502 std::unique_ptr
<weld::TreeIter
> ScAcceptChgDlg::AppendFilteredAction(
503 const ScChangeAction
* pScChangeAction
, ScChangeActionState eState
,
504 bool bCreateOnDemand
,
505 const weld::TreeIter
* pParent
, bool bDelMaster
, bool bDisabled
)
507 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
509 if(pScChangeAction
==nullptr || pChanges
==nullptr) return nullptr;
511 bool bIsGenerated
= pChanges
->IsGenerated(pScChangeAction
->GetActionNumber());
515 ScRange aRef
=pScChangeAction
->GetBigRange().MakeRange(*pDoc
);
516 const OUString
& aUser
=pScChangeAction
->GetUser();
517 DateTime aDateTime
=pScChangeAction
->GetDateTime();
519 if (pTheView
->IsValidEntry(aUser
, aDateTime
) || bIsGenerated
)
521 if(pTPFilter
->IsRange())
523 for ( size_t i
= 0, nRanges
= aRangeList
.size(); i
< nRanges
; ++i
)
525 ScRange
const & rRangeEntry
=aRangeList
[ i
];
526 if( rRangeEntry
.Intersects(aRef
) )
528 if( pScChangeAction
->GetState()==eState
)
534 else if(pScChangeAction
->GetState()==eState
&& !bIsGenerated
)
538 std::unique_ptr
<weld::TreeIter
> xEntry
;
541 ScChangeActionType eType
=pScChangeAction
->GetType();
542 OUString aActionString
;
545 std::unique_ptr
<ScRedlinData
> pNewData(new ScRedlinData
);
546 pNewData
->pData
=const_cast<ScChangeAction
*>(pScChangeAction
);
547 pNewData
->nActionNo
=pScChangeAction
->GetActionNumber();
548 pNewData
->bIsAcceptable
=pScChangeAction
->IsClickable();
549 pNewData
->bIsRejectable
=pScChangeAction
->IsRejectable();
550 pNewData
->bDisabled
=!pNewData
->bIsAcceptable
|| bDisabled
;
551 pNewData
->aDateTime
=aDateTime
;
552 pNewData
->nRow
= aRef
.aStart
.Row();
553 pNewData
->nCol
= aRef
.aStart
.Col();
554 pNewData
->nTable
= aRef
.aStart
.Tab();
556 if(eType
==SC_CAT_CONTENT
)
558 if(pScChangeAction
->IsDialogParent())
560 aActionString
=aStrContentWithChild
;
561 pNewData
->nInfo
=RD_SPECIAL_VISCONTENT
;
562 pNewData
->bIsRejectable
=false;
563 pNewData
->bIsAcceptable
=false;
567 aActionString
=*MakeTypeString(eType
);
568 aDesc
= pScChangeAction
->GetDescription(*pDoc
, true);
573 aActionString
=*MakeTypeString(eType
);
577 aDesc
= pScChangeAction
->GetDescription(*pDoc
,true);
578 pNewData
->bDisabled
=true;
579 pNewData
->bIsRejectable
=false;
582 aDesc
= pScChangeAction
->GetDescription(*pDoc
,!pScChangeAction
->IsMasterDelete());
587 OUString aComment
= pScChangeAction
->GetComment().replaceAll("\n", "");
588 if (!aDesc
.isEmpty())
590 aComment
+= " (" + aDesc
+ ")";
592 if (pTheView
->IsValidComment(aComment
))
594 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
595 xEntry
= rTreeView
.make_iterator();
596 OUString
sId(weld::toId(pNewData
.release()));
597 rTreeView
.insert(pParent
, -1, &aActionString
, &sId
, nullptr, nullptr, bCreateOnDemand
, xEntry
.get());
599 OUString aRefStr
= pScChangeAction
->GetRefString(*pDoc
, true);
600 rTreeView
.set_text(*xEntry
, aRefStr
, 1);
604 rTreeView
.set_text(*xEntry
, aUser
, 2);
605 OUString sDate
= ScGlobal::getLocaleData().getDate(aDateTime
) + " " + ScGlobal::getLocaleData().getTime(aDateTime
);
606 rTreeView
.set_text(*xEntry
, sDate
, 3);
609 rTreeView
.set_text(*xEntry
, aComment
, 4);
615 std::unique_ptr
<weld::TreeIter
> ScAcceptChgDlg::InsertChangeActionContent(const ScChangeActionContent
* pScChangeAction
,
616 const weld::TreeIter
& rParent
, sal_uLong nSpecial
)
618 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
620 if(pScChangeAction
==nullptr || pChanges
==nullptr) return nullptr;
622 bool bIsGenerated
= pChanges
->IsGenerated(pScChangeAction
->GetActionNumber());
626 ScRange aRef
=pScChangeAction
->GetBigRange().MakeRange(*pDoc
);
627 OUString aUser
=pScChangeAction
->GetUser();
628 DateTime aDateTime
=pScChangeAction
->GetDateTime();
630 if (pTheView
->IsValidEntry(aUser
, aDateTime
) || bIsGenerated
)
632 if(pTPFilter
->IsRange())
634 for ( size_t i
= 0, nRanges
= aRangeList
.size(); i
< nRanges
; ++i
)
636 ScRange
const & rRangeEntry
= aRangeList
[ i
];
637 if( rRangeEntry
.Intersects(aRef
) )
644 else if(!bIsGenerated
)
653 if(nSpecial
==RD_SPECIAL_CONTENT
)
655 aContent
= pScChangeAction
->GetOldString(pDoc
);
656 if (aContent
.isEmpty())
657 aContent
= aStrEmpty
;
658 aDesc
= aStrChildOrgContent
+ ": " + aContent
;
662 const OUString
aTmp( pScChangeAction
->GetNewString(pDoc
));
664 aContent
= aStrEmpty
;
666 aContent
= "\'" + aTmp
+ "\'";
667 aDesc
= aStrChildContent
+ aContent
;
670 aRefStr
= pScChangeAction
->GetRefString(*pDoc
, true);
675 aDate
= ScGlobal::getLocaleData().getDate(aDateTime
) + " " + ScGlobal::getLocaleData().getTime(aDateTime
);
682 OUString aComment
= pScChangeAction
->GetComment().replaceAll("\n", "");
686 aComment
+= " (" + aDesc
+ ")";
689 std::unique_ptr
<ScRedlinData
> pNewData(new ScRedlinData
);
690 pNewData
->nInfo
=nSpecial
;
691 pNewData
->pData
=const_cast<ScChangeActionContent
*>(pScChangeAction
);
692 pNewData
->nActionNo
=pScChangeAction
->GetActionNumber();
693 pNewData
->bIsAcceptable
=pScChangeAction
->IsClickable();
694 pNewData
->bIsRejectable
=false;
695 pNewData
->bDisabled
=!pNewData
->bIsAcceptable
;
696 pNewData
->aDateTime
=aDateTime
;
697 pNewData
->nRow
= aRef
.aStart
.Row();
698 pNewData
->nCol
= aRef
.aStart
.Col();
699 pNewData
->nTable
= aRef
.aStart
.Tab();
701 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
702 std::unique_ptr
<weld::TreeIter
> xEntry(rTreeView
.make_iterator());
703 OUString
sId(weld::toId(pNewData
.release()));
704 rTreeView
.insert(&rParent
, -1, &aContent
, &sId
, nullptr, nullptr, false, xEntry
.get());
705 rTreeView
.set_text( *xEntry
, aRefStr
, 1);
706 if (!aUser
.isEmpty())
707 rTreeView
.set_text( *xEntry
, aUser
, 2);
708 if (!aDate
.isEmpty())
709 rTreeView
.set_text( *xEntry
, aDate
, 3);
710 if (!aComment
.isEmpty())
711 rTreeView
.set_text( *xEntry
, aComment
, 4);
712 if (pTheView
->IsValidComment(aComment
) && bFlag
)
713 bHasFilterEntry
=true;
716 rTreeView
.set_font_color(*xEntry
, COL_LIGHTBLUE
);
721 void ScAcceptChgDlg::UpdateView()
723 std::unique_ptr
<weld::TreeIter
> xParent
;
724 ScChangeTrack
* pChanges
=nullptr;
725 const ScChangeAction
* pScChangeAction
=nullptr;
726 m_xDialog
->set_busy_cursor(true);
727 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
729 bool bFilterFlag
= pTPFilter
->IsDate() || pTPFilter
->IsRange() ||
730 pTPFilter
->IsAuthor() || pTPFilter
->IsComment();
732 bUseColor
= bFilterFlag
;
736 pChanges
=pDoc
->GetChangeTrack();
737 if(pChanges
!=nullptr)
738 pScChangeAction
=pChanges
->GetFirst();
740 bool bTheFlag
= false;
742 while(pScChangeAction
!=nullptr)
744 bHasFilterEntry
=false;
745 switch (pScChangeAction
->GetState())
749 if (pScChangeAction
->IsDialogRoot())
751 bool bOnDemandChildren
= !bFilterFlag
&& pScChangeAction
->IsDialogParent();
752 if (pScChangeAction
->IsDialogParent())
753 xParent
= AppendChangeAction(pScChangeAction
, bOnDemandChildren
);
755 xParent
= AppendFilteredAction(pScChangeAction
, SC_CAS_VIRGIN
, bOnDemandChildren
);
763 case SC_CAS_ACCEPTED
:
768 case SC_CAS_REJECTED
:
774 if (xParent
&& pScChangeAction
->IsDialogParent() && bFilterFlag
)
776 bool bTestFlag
= bHasFilterEntry
;
777 bHasFilterEntry
=false;
778 if (Expand(pChanges
, pScChangeAction
, *xParent
, !bTestFlag
) && !bTestFlag
)
779 rTreeView
.remove(*xParent
);
782 pScChangeAction
=pScChangeAction
->GetNext();
785 if( bTheFlag
&& (!pDoc
->IsDocEditable() || pChanges
->IsProtected()) )
788 pTPView
->EnableAccept(bTheFlag
);
789 pTPView
->EnableAcceptAll(bTheFlag
);
790 pTPView
->EnableReject(bTheFlag
);
791 pTPView
->EnableRejectAll(bTheFlag
);
794 rTreeView
.insert(nullptr, -1, &aStrAllAccepted
, nullptr, nullptr, nullptr, true, nullptr);
796 rTreeView
.insert(nullptr, -1, &aStrAllRejected
, nullptr, nullptr, nullptr, true, nullptr);
798 m_xDialog
->set_busy_cursor(false);
799 std::unique_ptr
<weld::TreeIter
> xEntry(rTreeView
.make_iterator());
800 if (rTreeView
.get_iter_first(*xEntry
))
801 rTreeView
.select(*xEntry
);
804 IMPL_LINK_NOARG(ScAcceptChgDlg
, RefHandle
, SvxTPFilter
*, void)
806 sal_uInt16 nId
=ScSimpleRefDlgWrapper::GetChildWindowId();
808 ScModule::get()->SetRefDialog(nId
, true);
810 SfxViewFrame
& rViewFrm
= pViewData
->GetViewShell()->GetViewFrame();
811 ScSimpleRefDlgWrapper
* pWnd
= static_cast<ScSimpleRefDlgWrapper
*>(rViewFrm
.GetChildWindow( nId
));
815 sal_uInt16 nAcceptId
=ScAcceptChgDlgWrapper::GetChildWindowId();
816 rViewFrm
.ShowChildWindow(nAcceptId
,false);
817 pWnd
->SetCloseHdl(LINK( this, ScAcceptChgDlg
,RefInfoHandle
));
818 pWnd
->SetRefString(pTPFilter
->GetRange());
819 ScSimpleRefDlgWrapper::SetAutoReOpen(false);
820 auto xWin
= pWnd
->GetController();
822 xWin
->set_title(m_xDialog
->get_title());
823 pWnd
->StartRefInput();
827 IMPL_LINK( ScAcceptChgDlg
, RefInfoHandle
, const OUString
*, pResult
, void)
829 sal_uInt16 nId
= ScAcceptChgDlgWrapper::GetChildWindowId();
831 ScSimpleRefDlgWrapper::SetAutoReOpen(true);
833 SfxViewFrame
& rViewFrm
= pViewData
->GetViewShell()->GetViewFrame();
836 pTPFilter
->SetRange(*pResult
);
837 FilterHandle(pTPFilter
);
839 rViewFrm
.ShowChildWindow(nId
);
843 rViewFrm
.SetChildWindow(nId
, false);
847 IMPL_LINK( ScAcceptChgDlg
, FilterHandle
, SvxTPFilter
*, pRef
, void )
852 aRangeList
.RemoveAll();
853 aRangeList
.Parse(pTPFilter
->GetRange(), *pDoc
);
858 IMPL_LINK( ScAcceptChgDlg
, RejectHandle
, SvxTPView
*, pRef
, void )
860 m_xDialog
->set_busy_cursor(true);
863 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
867 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
868 rTreeView
.selected_foreach([this, pChanges
, &rTreeView
](weld::TreeIter
& rEntry
){
869 ScRedlinData
*pEntryData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(rEntry
));
872 ScChangeAction
* pScChangeAction
= static_cast<ScChangeAction
*>(pEntryData
->pData
);
873 if (pScChangeAction
->GetType()==SC_CAT_INSERT_TABS
)
874 pViewData
->SetTabNo(0);
875 pChanges
->Reject(pScChangeAction
);
879 ScDocShell
* pDocSh
=pViewData
->GetDocShell();
880 pDocSh
->PostPaintExtras();
881 pDocSh
->PostPaintGridAll();
882 pDocSh
->GetUndoManager()->Clear();
883 pDocSh
->SetDocumentModified();
888 m_xDialog
->set_busy_cursor(false);
892 IMPL_LINK( ScAcceptChgDlg
, AcceptHandle
, SvxTPView
*, pRef
, void )
894 m_xDialog
->set_busy_cursor(true);
896 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
900 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
901 rTreeView
.selected_foreach([pChanges
, &rTreeView
](weld::TreeIter
& rEntry
) {
902 ScRedlinData
*pEntryData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(rEntry
));
905 ScChangeAction
* pScChangeAction
=
906 static_cast<ScChangeAction
*>(pEntryData
->pData
);
907 if(pScChangeAction
->GetType()==SC_CAT_CONTENT
)
909 if(pEntryData
->nInfo
==RD_SPECIAL_CONTENT
)
910 pChanges
->SelectContent(pScChangeAction
,true);
912 pChanges
->SelectContent(pScChangeAction
);
915 pChanges
->Accept(pScChangeAction
);
919 ScDocShell
* pDocSh
=pViewData
->GetDocShell();
920 pDocSh
->PostPaintExtras();
921 pDocSh
->PostPaintGridAll();
922 pDocSh
->SetDocumentModified();
926 m_xDialog
->set_busy_cursor(false);
930 void ScAcceptChgDlg::RejectFiltered()
932 if(pDoc
==nullptr) return;
933 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
934 const ScChangeAction
* pScChangeAction
=nullptr;
936 if(pChanges
!=nullptr)
938 pScChangeAction
=pChanges
->GetLast();
941 while(pScChangeAction
!=nullptr)
943 if(pScChangeAction
->IsDialogRoot())
944 if(IsValidAction(pScChangeAction
))
945 pChanges
->Reject(const_cast<ScChangeAction
*>(pScChangeAction
));
947 pScChangeAction
=pScChangeAction
->GetPrev();
950 void ScAcceptChgDlg::AcceptFiltered()
952 if(pDoc
==nullptr) return;
953 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
954 const ScChangeAction
* pScChangeAction
=nullptr;
956 if(pChanges
!=nullptr)
957 pScChangeAction
=pChanges
->GetLast();
959 while(pScChangeAction
!=nullptr)
961 if(pScChangeAction
->IsDialogRoot())
962 if(IsValidAction(pScChangeAction
))
963 pChanges
->Accept(const_cast<ScChangeAction
*>(pScChangeAction
));
965 pScChangeAction
=pScChangeAction
->GetPrev();
969 IMPL_LINK_NOARG(ScAcceptChgDlg
, RejectAllHandle
, SvxTPView
*, void)
971 m_xDialog
->set_busy_cursor(true);
973 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
974 if(pChanges
!=nullptr)
976 if(pTPFilter
->IsDate()||pTPFilter
->IsAuthor()||pTPFilter
->IsRange()||pTPFilter
->IsComment())
979 pChanges
->RejectAll();
981 pViewData
->SetTabNo(0);
983 ScDocShell
* pDocSh
=pViewData
->GetDocShell();
984 pDocSh
->PostPaintExtras();
985 pDocSh
->PostPaintGridAll();
986 pDocSh
->GetUndoManager()->Clear();
987 pDocSh
->SetDocumentModified();
991 m_xDialog
->set_busy_cursor(false);
996 IMPL_LINK_NOARG(ScAcceptChgDlg
, AcceptAllHandle
, SvxTPView
*, void)
998 m_xDialog
->set_busy_cursor(true);
1001 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
1002 if(pChanges
!=nullptr)
1004 if(pTPFilter
->IsDate()||pTPFilter
->IsAuthor()||pTPFilter
->IsRange()||pTPFilter
->IsComment())
1007 pChanges
->AcceptAll();
1009 ScDocShell
* pDocSh
=pViewData
->GetDocShell();
1010 pDocSh
->PostPaintExtras();
1011 pDocSh
->PostPaintGridAll();
1012 pDocSh
->SetDocumentModified();
1018 m_xDialog
->set_busy_cursor(false);
1021 IMPL_LINK_NOARG(ScAcceptChgDlg
, SelectHandle
, weld::TreeView
&, void)
1024 aSelectionIdle
.Start();
1029 void ScAcceptChgDlg::GetDependents(const ScChangeAction
* pScChangeAction
,
1030 ScChangeActionMap
& aActionMap
,
1031 const weld::TreeIter
& rEntry
)
1033 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
1035 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1036 std::unique_ptr
<weld::TreeIter
> xParent(rTreeView
.make_iterator(&rEntry
));
1037 if (rTreeView
.iter_parent(*xParent
))
1039 ScRedlinData
*pParentData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(*xParent
));
1040 ScChangeAction
* pParentAction
=static_cast<ScChangeAction
*>(pParentData
->pData
);
1042 if(pParentAction
!=pScChangeAction
)
1043 pChanges
->GetDependents(const_cast<ScChangeAction
*>(pScChangeAction
),
1044 aActionMap
,pScChangeAction
->IsMasterDelete());
1046 pChanges
->GetDependents( const_cast<ScChangeAction
*>(pScChangeAction
),
1050 pChanges
->GetDependents(const_cast<ScChangeAction
*>(pScChangeAction
),
1051 aActionMap
, pScChangeAction
->IsMasterDelete() );
1054 bool ScAcceptChgDlg::InsertContentChildren(ScChangeActionMap
* pActionMap
, const weld::TreeIter
& rParent
)
1056 bool bTheTestFlag
= true;
1057 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1058 ScRedlinData
*pEntryData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(rParent
));
1059 const ScChangeAction
* pScChangeAction
= static_cast<ScChangeAction
*>(pEntryData
->pData
);
1060 bool bParentInserted
= false;
1061 // If the parent is a MatrixOrigin then place it in the right order before
1062 // the MatrixReferences. Also if it is the first content change at this
1063 // position don't insert the first dependent MatrixReference as the special
1064 // content (original value) but insert the predecessor of the MatrixOrigin
1066 if ( pScChangeAction
->GetType() == SC_CAT_CONTENT
&&
1067 static_cast<const ScChangeActionContent
*>(pScChangeAction
)->IsMatrixOrigin() )
1069 pActionMap
->insert( ::std::make_pair( pScChangeAction
->GetActionNumber(),
1070 const_cast<ScChangeAction
*>( pScChangeAction
) ) );
1071 bParentInserted
= true;
1074 ScChangeActionMap::iterator itChangeAction
= std::find_if(pActionMap
->begin(), pActionMap
->end(),
1075 [](const std::pair
<sal_uLong
, ScChangeAction
*>& rEntry
) { return rEntry
.second
->GetState() == SC_CAS_VIRGIN
; });
1077 if( itChangeAction
== pActionMap
->end() )
1080 std::unique_ptr
<weld::TreeIter
> xOriginal
= InsertChangeActionContent(
1081 dynamic_cast<const ScChangeActionContent
*>( itChangeAction
->second
),
1082 rParent
, RD_SPECIAL_CONTENT
);
1087 ScRedlinData
*pParentData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(*xOriginal
));
1088 pParentData
->pData
=const_cast<ScChangeAction
*>(pScChangeAction
);
1089 pParentData
->nActionNo
=pScChangeAction
->GetActionNumber();
1090 pParentData
->bIsAcceptable
=pScChangeAction
->IsRejectable(); // select old value
1091 pParentData
->bIsRejectable
=false;
1092 pParentData
->bDisabled
=false;
1094 while( itChangeAction
!= pActionMap
->end() )
1096 if( itChangeAction
->second
->GetState() == SC_CAS_VIRGIN
)
1098 std::unique_ptr
<weld::TreeIter
> xEntry
=
1099 InsertChangeActionContent( dynamic_cast<const ScChangeActionContent
*>( itChangeAction
->second
),
1100 rParent
, RD_SPECIAL_NONE
);
1108 if ( !bParentInserted
)
1110 std::unique_ptr
<weld::TreeIter
> xEntry
=
1111 InsertChangeActionContent(static_cast<const ScChangeActionContent
*>(
1112 pScChangeAction
),rParent
,RD_SPECIAL_NONE
);
1117 ScRedlinData
*pParentData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(*xEntry
));
1118 pParentData
->pData
=const_cast<ScChangeAction
*>(pScChangeAction
);
1119 pParentData
->nActionNo
=pScChangeAction
->GetActionNumber();
1120 pParentData
->bIsAcceptable
=pScChangeAction
->IsClickable();
1121 pParentData
->bIsRejectable
=false;
1122 pParentData
->bDisabled
=false;
1126 return bTheTestFlag
;
1129 bool ScAcceptChgDlg::InsertAcceptedORejected(const weld::TreeIter
& rParent
)
1131 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
1132 bool bTheTestFlag
= true;
1134 ScChangeActionState eState
= SC_CAS_VIRGIN
;
1135 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1136 OUString aString
= rTreeView
.get_text(rParent
, 0);
1137 OUString a2String
= aString
.copy(0, aStrAllAccepted
.getLength());
1138 if (a2String
== aStrAllAccepted
)
1139 eState
=SC_CAS_ACCEPTED
;
1142 a2String
= aString
.copy(0, aStrAllRejected
.getLength());
1143 if (a2String
== aStrAllRejected
)
1144 eState
=SC_CAS_REJECTED
;
1147 ScChangeAction
* pScChangeAction
= pChanges
->GetFirst();
1148 while (pScChangeAction
)
1150 if (pScChangeAction
->GetState()==eState
&&
1151 AppendFilteredAction(pScChangeAction
, eState
, false, &rParent
))
1153 pScChangeAction
=pScChangeAction
->GetNext();
1155 return bTheTestFlag
;
1158 bool ScAcceptChgDlg::InsertChildren(ScChangeActionMap
* pActionMap
, const weld::TreeIter
& rParent
)
1160 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
1161 bool bTheTestFlag
= true;
1163 for( const auto& rChangeAction
: *pActionMap
)
1165 std::unique_ptr
<weld::TreeIter
> xEntry
= AppendChangeAction(rChangeAction
.second
, false, &rParent
, false, true);
1171 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1172 ScRedlinData
*pEntryData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(*xEntry
));
1173 pEntryData
->bIsRejectable
=false;
1174 pEntryData
->bIsAcceptable
=false;
1175 pEntryData
->bDisabled
=true;
1177 if (rChangeAction
.second
->IsDialogParent())
1178 Expand(pChanges
, rChangeAction
.second
, *xEntry
);
1181 return bTheTestFlag
;
1184 bool ScAcceptChgDlg::InsertDeletedChildren(const ScChangeAction
* pScChangeAction
,
1185 ScChangeActionMap
* pActionMap
, const weld::TreeIter
& rParent
)
1187 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
1188 bool bTheTestFlag
= true;
1189 std::unique_ptr
<weld::TreeIter
> xEntry
;
1191 for( const auto& rChangeAction
: *pActionMap
)
1194 if( pScChangeAction
!= rChangeAction
.second
)
1195 xEntry
= AppendChangeAction(rChangeAction
.second
, false, &rParent
, false, true);
1197 xEntry
= AppendChangeAction(rChangeAction
.second
, false, &rParent
, true, true);
1201 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1202 ScRedlinData
*pEntryData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(*xEntry
));
1203 pEntryData
->bIsRejectable
=false;
1204 pEntryData
->bIsAcceptable
=false;
1205 pEntryData
->bDisabled
=true;
1209 if (rChangeAction
.second
->IsDialogParent())
1210 Expand(pChanges
, rChangeAction
.second
, *xEntry
);
1213 return bTheTestFlag
;
1216 bool ScAcceptChgDlg::Expand(const ScChangeTrack
* pChanges
, const ScChangeAction
* pScChangeAction
,
1217 const weld::TreeIter
& rEntry
, bool bFilter
)
1219 bool bTheTestFlag
= true;
1221 if (pChanges
&& pScChangeAction
)
1223 ScChangeActionMap aActionMap
;
1225 GetDependents(pScChangeAction
, aActionMap
, rEntry
);
1227 switch(pScChangeAction
->GetType())
1229 case SC_CAT_CONTENT
:
1231 InsertContentChildren(&aActionMap
, rEntry
);
1232 bTheTestFlag
=!bHasFilterEntry
;
1235 case SC_CAT_DELETE_COLS
:
1236 case SC_CAT_DELETE_ROWS
:
1237 case SC_CAT_DELETE_TABS
:
1239 InsertDeletedChildren(pScChangeAction
, &aActionMap
, rEntry
);
1240 bTheTestFlag
=!bHasFilterEntry
;
1246 bTheTestFlag
= InsertChildren(&aActionMap
, rEntry
);
1252 return bTheTestFlag
;
1255 IMPL_LINK(ScAcceptChgDlg
, ExpandingHandle
, const weld::TreeIter
&, rEntry
, bool)
1257 ScChangeTrack
* pChanges
=pDoc
->GetChangeTrack();
1260 m_xDialog
->set_busy_cursor(true);
1261 ScChangeActionMap aActionMap
;
1262 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1263 ScRedlinData
*pEntryData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(rEntry
));
1264 if (!rTreeView
.iter_has_child(rEntry
))
1266 bool bTheTestFlag
= true;
1270 ScChangeAction
* pScChangeAction
=static_cast<ScChangeAction
*>(pEntryData
->pData
);
1272 GetDependents(pScChangeAction
, aActionMap
, rEntry
);
1274 switch (pScChangeAction
->GetType())
1276 case SC_CAT_CONTENT
:
1278 bTheTestFlag
= InsertContentChildren( &aActionMap
, rEntry
);
1281 case SC_CAT_DELETE_COLS
:
1282 case SC_CAT_DELETE_ROWS
:
1283 case SC_CAT_DELETE_TABS
:
1285 bTheTestFlag
= InsertDeletedChildren( pScChangeAction
, &aActionMap
, rEntry
);
1290 bTheTestFlag
= InsertChildren( &aActionMap
, rEntry
);
1299 bTheTestFlag
= InsertAcceptedORejected(rEntry
);
1303 std::unique_ptr
<weld::TreeIter
> xEntry(rTreeView
.make_iterator());
1304 rTreeView
.insert(&rEntry
, -1, &aStrNoEntry
, nullptr, nullptr, nullptr, false, xEntry
.get());
1305 rTreeView
.set_font_color(*xEntry
, COL_GRAY
);
1308 m_xDialog
->set_busy_cursor(false);
1313 void ScAcceptChgDlg::AppendChanges(const ScChangeTrack
* pChanges
,sal_uLong nStartAction
,
1314 sal_uLong nEndAction
)
1316 if(pChanges
==nullptr)
1319 std::unique_ptr
<weld::TreeIter
> xParent
;
1320 m_xDialog
->set_busy_cursor(true);
1321 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1324 bool bTheFlag
= false;
1326 bool bFilterFlag
= pTPFilter
->IsDate() || pTPFilter
->IsRange() ||
1327 pTPFilter
->IsAuthor() || pTPFilter
->IsComment();
1329 bUseColor
= bFilterFlag
;
1331 for(sal_uLong i
=nStartAction
;i
<=nEndAction
;i
++)
1333 const ScChangeAction
* pScChangeAction
=pChanges
->GetAction(i
);
1334 if(pScChangeAction
==nullptr) continue;
1336 switch (pScChangeAction
->GetState())
1340 if (pScChangeAction
->IsDialogRoot())
1342 bool bOnDemandChildren
= !bFilterFlag
&& pScChangeAction
->IsDialogParent();
1343 if (pScChangeAction
->IsDialogParent())
1344 xParent
= AppendChangeAction(pScChangeAction
, bOnDemandChildren
);
1346 xParent
= AppendFilteredAction(pScChangeAction
, SC_CAS_VIRGIN
, bOnDemandChildren
);
1354 case SC_CAS_ACCEPTED
:
1359 case SC_CAS_REJECTED
:
1365 if (xParent
&& pScChangeAction
->IsDialogParent() && bFilterFlag
)
1367 bool bTestFlag
= bHasFilterEntry
;
1368 bHasFilterEntry
= false;
1369 if (Expand(pChanges
,pScChangeAction
,*xParent
,!bTestFlag
)&&!bTestFlag
)
1370 rTreeView
.remove(*xParent
);
1374 if( bTheFlag
&& (!pDoc
->IsDocEditable() || pChanges
->IsProtected()) )
1377 pTPView
->EnableAccept(bTheFlag
);
1378 pTPView
->EnableAcceptAll(bTheFlag
);
1379 pTPView
->EnableReject(bTheFlag
);
1380 pTPView
->EnableRejectAll(bTheFlag
);
1383 m_xDialog
->set_busy_cursor(false);
1386 void ScAcceptChgDlg::RemoveEntries(sal_uLong nStartAction
,sal_uLong nEndAction
)
1388 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1390 ScRedlinData
*pEntryData
=nullptr;
1391 std::unique_ptr
<weld::TreeIter
> xEntry(rTreeView
.make_iterator());
1392 if (rTreeView
.get_cursor(xEntry
.get()))
1393 pEntryData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(*xEntry
));
1395 if (!rTreeView
.get_iter_first(*xEntry
))
1398 sal_uLong nAction
=0;
1400 nAction
=pEntryData
->nActionNo
;
1402 if (nAction
>=nStartAction
&& nAction
<=nEndAction
)
1403 rTreeView
.set_cursor(*xEntry
);
1405 std::vector
<OUString
> aIdsToRemove
;
1409 OUString
sId(rTreeView
.get_id(*xEntry
));
1410 pEntryData
= weld::fromId
<ScRedlinData
*>(sId
);
1413 nAction
= pEntryData
->nActionNo
;
1414 if (nStartAction
<= nAction
&& nAction
<= nEndAction
)
1416 aIdsToRemove
.push_back(sId
);
1421 while (rTreeView
.iter_next(*xEntry
));
1425 // MUST do it backwards, don't delete parents before children and GPF
1426 for (auto it
= aIdsToRemove
.rbegin(); it
!= aIdsToRemove
.rend(); ++it
)
1427 rTreeView
.remove_id(*it
);
1432 void ScAcceptChgDlg::UpdateEntries(const ScChangeTrack
* pChgTrack
, sal_uLong nStartAction
,sal_uLong nEndAction
)
1434 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1437 std::unique_ptr
<weld::TreeIter
> xEntry(rTreeView
.make_iterator());
1438 std::unique_ptr
<weld::TreeIter
> xLastEntry(rTreeView
.make_iterator());
1439 std::unique_ptr
<weld::TreeIter
> xNextEntry(rTreeView
.make_iterator());
1441 bool bEntry
= rTreeView
.get_iter_first(*xEntry
);
1442 bool bLastEntry
= false;
1446 bool bRemove
= false;
1447 ScRedlinData
*pEntryData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(*xEntry
));
1450 ScChangeAction
* pScChangeAction
=
1451 static_cast<ScChangeAction
*>(pEntryData
->pData
);
1453 sal_uLong nAction
=pScChangeAction
->GetActionNumber();
1455 if(nStartAction
<=nAction
&& nAction
<=nEndAction
) bRemove
=true;
1461 rTreeView
.remove(*xEntry
);
1465 bLastEntry
= rTreeView
.get_iter_first(*xLastEntry
);
1468 rTreeView
.copy_iterator(*xLastEntry
, *xNextEntry
);
1469 bNextEntry
= rTreeView
.iter_next(*xNextEntry
);
1472 rTreeView
.copy_iterator(*xLastEntry
, *xNextEntry
);
1481 rTreeView
.copy_iterator(*xEntry
, *xLastEntry
);
1484 rTreeView
.copy_iterator(*xEntry
, *xNextEntry
);
1485 bNextEntry
= rTreeView
.iter_next(*xNextEntry
);
1488 rTreeView
.copy_iterator(*xNextEntry
, *xEntry
);
1489 bEntry
= bNextEntry
;
1492 AppendChanges(pChgTrack
,nStartAction
,nEndAction
);
1497 IMPL_LINK( ScAcceptChgDlg
, ChgTrackModHdl
, ScChangeTrack
&, rChgTrack
, void)
1499 ScChangeTrackMsgQueue
& aMsgQueue
= rChgTrack
.GetMsgQueue();
1501 sal_uLong nStartAction
;
1502 sal_uLong nEndAction
;
1504 for (const auto& rMsg
: aMsgQueue
)
1506 nStartAction
= rMsg
.nStartAction
;
1507 nEndAction
= rMsg
.nEndAction
;
1513 switch(rMsg
.eMsgType
)
1515 case ScChangeTrackMsgType::Append
:
1516 AppendChanges(&rChgTrack
,nStartAction
,nEndAction
);
1518 case ScChangeTrackMsgType::Remove
:
1519 RemoveEntries(nStartAction
,nEndAction
);
1521 case ScChangeTrackMsgType::Parent
:
1522 case ScChangeTrackMsgType::Change
: //bNeedsUpdate=true;
1523 UpdateEntries(&rChgTrack
,nStartAction
,nEndAction
);
1525 default: assert(false); break;
1533 IMPL_LINK_NOARG(ScAcceptChgDlg
, ReOpenTimerHdl
, Timer
*, void)
1535 ScSimpleRefDlgWrapper::SetAutoReOpen(true);
1536 m_xAcceptChgCtr
->ShowFilterPage();
1540 IMPL_LINK_NOARG(ScAcceptChgDlg
, UpdateSelectionHdl
, Timer
*, void)
1542 ScTabView
* pTabView
= pViewData
->GetView();
1544 bool bAcceptFlag
= true;
1545 bool bRejectFlag
= true;
1547 pTabView
->DoneBlockMode(); // clears old marking
1548 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1549 std::vector
<const ScChangeAction
*> aActions
;
1550 rTreeView
.selected_foreach([&rTreeView
, &bAcceptFlag
, &bRejectFlag
, &aActions
](weld::TreeIter
& rEntry
){
1551 ScRedlinData
* pEntryData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(rEntry
));
1554 bRejectFlag
&= pEntryData
->bIsRejectable
;
1555 bAcceptFlag
&= pEntryData
->bIsAcceptable
;
1557 const ScChangeAction
* pScChangeAction
= static_cast<ScChangeAction
*>(pEntryData
->pData
);
1558 if( pScChangeAction
&& (pScChangeAction
->GetType() != SC_CAT_DELETE_TABS
) &&
1559 (!pEntryData
->bDisabled
|| pScChangeAction
->IsVisible()) )
1561 aActions
.push_back(pScChangeAction
);
1566 bAcceptFlag
= false;
1567 bRejectFlag
= false;
1572 bool bContMark
= false;
1573 for (size_t i
= 0, nCount
= aActions
.size(); i
< nCount
; ++i
)
1575 const ScBigRange
& rBigRange
= aActions
[i
]->GetBigRange();
1576 if (rBigRange
.IsValid(*pDoc
) && m_xDialog
->has_toplevel_focus())
1578 bool bSetCursor
= i
== nCount
- 1;
1579 pTabView
->MarkRange(rBigRange
.MakeRange(*pDoc
), bSetCursor
, bContMark
);
1584 ScChangeTrack
* pChanges
= pDoc
->GetChangeTrack();
1585 bool bEnable
= pDoc
->IsDocEditable() && pChanges
&& !pChanges
->IsProtected();
1586 pTPView
->EnableAccept( bAcceptFlag
&& bEnable
);
1587 pTPView
->EnableReject( bRejectFlag
&& bEnable
);
1590 IMPL_LINK(ScAcceptChgDlg
, CommandHdl
, const CommandEvent
&, rCEvt
, bool)
1592 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
)
1595 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1596 std::unique_ptr
<weld::TreeIter
> xEntry(rTreeView
.make_iterator());
1597 bool bEntry
= rTreeView
.get_cursor(xEntry
.get());
1599 rTreeView
.select(*xEntry
);
1601 int nSortedCol
= rTreeView
.get_sort_column();
1602 for (sal_Int32 i
= 0; i
< 5; ++i
)
1603 m_xSortMenu
->set_active("calcsort" + OUString::number(i
), i
== nSortedCol
);
1605 m_xPopup
->set_sensitive(u
"calcedit"_ustr
, false);
1607 if (pDoc
->IsDocEditable() && bEntry
)
1609 ScRedlinData
*pEntryData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(*xEntry
));
1612 ScChangeAction
* pScChangeAction
= static_cast<ScChangeAction
*>(pEntryData
->pData
);
1613 if (pScChangeAction
&& !rTreeView
.get_iter_depth(*xEntry
))
1614 m_xPopup
->set_sensitive(u
"calcedit"_ustr
, true);
1618 OUString sCommand
= m_xPopup
->popup_at_rect(&rTreeView
, tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1,1)));
1620 if (!sCommand
.isEmpty())
1622 if (sCommand
== "calcedit")
1626 ScRedlinData
*pEntryData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(*xEntry
));
1629 ScChangeAction
* pScChangeAction
= static_cast<ScChangeAction
*>(pEntryData
->pData
);
1630 pViewData
->GetDocShell()->ExecuteChangeCommentDialog(pScChangeAction
, m_xDialog
.get(), false);
1636 int nDialogCol
= o3tl::toInt32(sCommand
.subView(8));
1637 pTheView
->HeaderBarClick(nDialogCol
);
1646 //at one point we were writing multiple AcceptChgDat strings,
1647 //so strip all of them and keep the results of the last one
1648 OUString
lcl_StripAcceptChgDat(OUString
&rExtraString
)
1653 sal_Int32 nPos
= rExtraString
.indexOf("AcceptChgDat:");
1656 // Try to read the alignment string "ALIGN:(...)"; if it is missing
1657 // we have an old version
1658 sal_Int32 n1
= rExtraString
.indexOf('(', nPos
);
1661 sal_Int32 n2
= rExtraString
.indexOf(')', n1
);
1664 // cut out alignment string
1665 aStr
= rExtraString
.copy(nPos
, n2
- nPos
+ 1);
1666 rExtraString
= rExtraString
.replaceAt(nPos
, n2
- nPos
+ 1, u
"");
1667 aStr
= aStr
.copy( n1
-nPos
+1 );
1675 void ScAcceptChgDlg::Initialize(SfxChildWinInfo
* pInfo
)
1678 if (pInfo
&& !pInfo
->aExtraString
.isEmpty())
1679 aStr
= lcl_StripAcceptChgDat(pInfo
->aExtraString
);
1681 SfxModelessDialogController::Initialize(pInfo
);
1686 int nCount
= aStr
.toInt32();
1690 std::vector
<int> aEndPos
;
1692 for (int i
= 0; i
< nCount
; ++i
)
1694 sal_Int32 n1
= aStr
.indexOf(';');
1695 aStr
= aStr
.copy( n1
+1 );
1696 aEndPos
.push_back(aStr
.toInt32());
1699 std::vector
<int> aWidths
;
1700 for (int i
= 1; i
< nCount
; ++i
)
1701 aWidths
.push_back(aEndPos
[i
] - aEndPos
[i
- 1]);
1703 // turn column end points back to column widths, ignoring the small
1704 // value used for the expander column
1705 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1706 rTreeView
.set_column_fixed_widths(aWidths
);
1709 void ScAcceptChgDlg::FillInfo(SfxChildWinInfo
& rInfo
) const
1711 SfxModelessDialogController::FillInfo(rInfo
);
1712 //remove any old one before adding a new one
1713 lcl_StripAcceptChgDat(rInfo
.aExtraString
);
1714 rInfo
.aExtraString
+= "AcceptChgDat:(";
1716 const int nTabCount
= 5;
1718 rInfo
.aExtraString
+= OUString::number(nTabCount
);
1719 rInfo
.aExtraString
+= ";";
1721 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1722 std::vector
<int> aWidths
;
1723 // turn column widths back into column end points for compatibility
1724 // with how they used to be stored, including a small value for the
1726 aWidths
.push_back(rTreeView
.get_checkbox_column_width());
1727 for (int i
= 0; i
< nTabCount
- 1; ++i
)
1728 aWidths
.push_back(aWidths
.back() + rTreeView
.get_column_width(i
));
1730 for (auto a
: aWidths
)
1732 rInfo
.aExtraString
+= OUString::number(a
);
1733 rInfo
.aExtraString
+= ";";
1735 rInfo
.aExtraString
+= ")";
1741 int ScAcceptChgDlg::ColCompareHdl(const weld::TreeIter
& rLeft
, const weld::TreeIter
& rRight
) const
1743 weld::TreeView
& rTreeView
= pTheView
->GetWidget();
1745 sal_Int32 nCompare
= 0;
1746 SCCOL nSortCol
= rTreeView
.get_sort_column();
1748 if (CALC_DATE
== nSortCol
)
1750 RedlinData
*pLeftData
= weld::fromId
<RedlinData
*>(rTreeView
.get_id(rLeft
));
1751 RedlinData
*pRightData
= weld::fromId
<RedlinData
*>(rTreeView
.get_id(rRight
));
1752 if (pLeftData
&& pRightData
)
1754 if(pLeftData
->aDateTime
< pRightData
->aDateTime
)
1756 else if(pLeftData
->aDateTime
> pRightData
->aDateTime
)
1761 else if (CALC_POS
== nSortCol
)
1763 ScRedlinData
*pLeftData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(rLeft
));
1764 ScRedlinData
*pRightData
= weld::fromId
<ScRedlinData
*>(rTreeView
.get_id(rRight
));
1765 if (pLeftData
&& pRightData
)
1769 if(pLeftData
->nTable
< pRightData
->nTable
)
1771 else if(pLeftData
->nTable
== pRightData
->nTable
)
1773 if(pLeftData
->nRow
< pRightData
->nRow
)
1775 else if(pLeftData
->nRow
== pRightData
->nRow
)
1777 if(pLeftData
->nCol
< pRightData
->nCol
)
1779 else if(pLeftData
->nCol
== pRightData
->nCol
)
1788 return ScGlobal::GetCaseCollator().compareString(rTreeView
.get_text(rLeft
, nSortCol
),
1789 rTreeView
.get_text(rRight
, nSortCol
));
1792 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */