/src/libreoffice/sc/source/ui/miscdlgs/acredlin.cxx
Line | Count | Source |
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 <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 <vcl/weld/Dialog.hxx> |
28 | | #include <vcl/weld/Menu.hxx> |
29 | | #include <o3tl/string_view.hxx> |
30 | | |
31 | | #include <acredlin.hxx> |
32 | | #include <global.hxx> |
33 | | #include <reffact.hxx> |
34 | | #include <document.hxx> |
35 | | #include <docsh.hxx> |
36 | | #include <scresid.hxx> |
37 | | #include <strings.hrc> |
38 | | #include <scmod.hxx> |
39 | | #include <tabvwsh.hxx> |
40 | | |
41 | | // defines ------------------------------------------------------------------- |
42 | | |
43 | 0 | #define RD_SPECIAL_NONE 0 |
44 | 0 | #define RD_SPECIAL_CONTENT 1 |
45 | 0 | #define RD_SPECIAL_VISCONTENT 2 |
46 | | |
47 | | |
48 | | ScRedlineData::ScRedlineData() |
49 | 0 | { |
50 | 0 | nInfo=RD_SPECIAL_NONE; |
51 | 0 | nActionNo=0; |
52 | 0 | pData=nullptr; |
53 | 0 | bDisabled=false; |
54 | 0 | bIsRejectable=false; |
55 | 0 | bIsAcceptable=false; |
56 | 0 | nTable=SCTAB_MAX; |
57 | 0 | nCol=SCCOL_MAX; |
58 | 0 | nRow=SCROW_MAX; |
59 | 0 | } |
60 | | |
61 | | ScRedlineData::~ScRedlineData() |
62 | 0 | { |
63 | 0 | nInfo=RD_SPECIAL_NONE; |
64 | 0 | nActionNo=0; |
65 | 0 | pData=nullptr; |
66 | 0 | bDisabled=false; |
67 | 0 | bIsRejectable=false; |
68 | 0 | bIsAcceptable=false; |
69 | 0 | } |
70 | | |
71 | | |
72 | | ScAcceptChgDlg::ScAcceptChgDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent, |
73 | | ScViewData& rViewData) |
74 | 0 | : SfxModelessDialogController(pB, pCW, pParent, |
75 | 0 | u"svx/ui/acceptrejectchangesdialog.ui"_ustr, u"AcceptRejectChangesDialog"_ustr) |
76 | 0 | , aSelectionIdle( "ScAcceptChgDlg aSelectionIdle" ) |
77 | 0 | , aReOpenIdle("ScAcceptChgDlg ReOpenIdle") |
78 | 0 | , pViewData( &rViewData ) |
79 | 0 | , pDoc( &rViewData.GetDocument() ) |
80 | 0 | , aStrInsertCols(ScResId(STR_CHG_INSERT_COLS)) |
81 | 0 | , aStrInsertRows(ScResId(STR_CHG_INSERT_ROWS)) |
82 | 0 | , aStrInsertTabs(ScResId(STR_CHG_INSERT_TABS)) |
83 | 0 | , aStrDeleteCols(ScResId(STR_CHG_DELETE_COLS)) |
84 | 0 | , aStrDeleteRows(ScResId(STR_CHG_DELETE_ROWS)) |
85 | 0 | , aStrDeleteTabs(ScResId(STR_CHG_DELETE_TABS)) |
86 | 0 | , aStrMove(ScResId(STR_CHG_MOVE)) |
87 | 0 | , aStrContent(ScResId(STR_CHG_CONTENT)) |
88 | 0 | , aStrReject(ScResId(STR_CHG_REJECT)) |
89 | 0 | , aStrAllAccepted(ScResId(STR_CHG_ACCEPTED)) |
90 | 0 | , aStrAllRejected(ScResId(STR_CHG_REJECTED)) |
91 | 0 | , aStrNoEntry(ScResId(STR_CHG_NO_ENTRY)) |
92 | 0 | , aStrContentWithChild(ScResId(STR_CHG_CONTENT_WITH_CHILD)) |
93 | 0 | , aStrChildContent(ScResId(STR_CHG_CHILD_CONTENT)) |
94 | 0 | , aStrChildOrgContent(ScResId(STR_CHG_CHILD_ORGCONTENT)) |
95 | 0 | , aStrEmpty(ScResId(STR_CHG_EMPTY)) |
96 | 0 | , aUnknown(u"Unknown"_ustr) |
97 | 0 | , bIgnoreMsg(false) |
98 | 0 | , bNoSelection(false) |
99 | 0 | , bHasFilterEntry(false) |
100 | 0 | , bUseColor(false) |
101 | 0 | , m_xContentArea(m_xDialog->weld_content_area()) |
102 | 0 | , m_xPopup(m_xBuilder->weld_menu(u"calcmenu"_ustr)) |
103 | 0 | , m_xSortMenu(m_xBuilder->weld_menu(u"calcsortmenu"_ustr)) |
104 | 0 | , m_xAcceptChgCtr(new SvxAcceptChgCtr(m_xContentArea.get())) |
105 | 0 | , m_rTPView(m_xAcceptChgCtr->GetViewPage()) |
106 | 0 | { |
107 | 0 | nAcceptCount=0; |
108 | 0 | nRejectCount=0; |
109 | 0 | aReOpenIdle.SetInvokeHandler(LINK( this, ScAcceptChgDlg, ReOpenTimerHdl )); |
110 | |
|
111 | 0 | pTPFilter = m_xAcceptChgCtr->GetFilterPage(); |
112 | | |
113 | | // tdf#136062 Don't use "Reject/Clear formatting" instead of "Reject" buttons in Calc |
114 | 0 | m_rTPView.EnableClearFormat(false); |
115 | 0 | m_rTPView.EnableClearFormatAll(false); |
116 | |
|
117 | 0 | pTheView = m_rTPView.GetTableControl(); |
118 | 0 | pTheView->SetCalcView(); |
119 | 0 | aSelectionIdle.SetInvokeHandler(LINK( this, ScAcceptChgDlg, UpdateSelectionHdl )); |
120 | |
|
121 | 0 | pTPFilter->SetReadyHdl(LINK( this, ScAcceptChgDlg, FilterHandle )); |
122 | 0 | pTPFilter->SetRefHdl(LINK( this, ScAcceptChgDlg, RefHandle )); |
123 | 0 | pTPFilter->HideRange(false); |
124 | 0 | m_rTPView.SetRejectClickHdl(LINK(this, ScAcceptChgDlg, RejectHandle)); |
125 | 0 | m_rTPView.SetAcceptClickHdl(LINK(this, ScAcceptChgDlg, AcceptHandle)); |
126 | 0 | m_rTPView.SetRejectAllClickHdl(LINK(this, ScAcceptChgDlg, RejectAllHandle)); |
127 | 0 | m_rTPView.SetAcceptAllClickHdl(LINK(this, ScAcceptChgDlg, AcceptAllHandle)); |
128 | |
|
129 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
130 | 0 | rTreeView.connect_expanding(LINK(this, ScAcceptChgDlg, ExpandingHandle)); |
131 | 0 | rTreeView.connect_selection_changed(LINK(this, ScAcceptChgDlg, SelectHandle)); |
132 | 0 | rTreeView.connect_command(LINK(this, ScAcceptChgDlg, CommandHdl)); |
133 | 0 | rTreeView.set_sort_func([this](const weld::TreeIter& rLeft, const weld::TreeIter& rRight){ |
134 | 0 | return ColCompareHdl(rLeft, rRight); |
135 | 0 | }); |
136 | 0 | rTreeView.set_selection_mode(SelectionMode::Multiple); |
137 | |
|
138 | 0 | Init(); |
139 | |
|
140 | 0 | UpdateView(); |
141 | |
|
142 | 0 | std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator()); |
143 | 0 | if (rTreeView.get_iter_first(*xEntry)) |
144 | 0 | rTreeView.select(*xEntry); |
145 | 0 | } |
146 | | |
147 | | ScAcceptChgDlg::~ScAcceptChgDlg() |
148 | 0 | { |
149 | 0 | ClearView(); |
150 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
151 | |
|
152 | 0 | if (pChanges) |
153 | 0 | { |
154 | 0 | Link<ScChangeTrack&,void> aLink; |
155 | 0 | pChanges->SetModifiedLink(aLink); |
156 | 0 | } |
157 | 0 | } |
158 | | |
159 | | void ScAcceptChgDlg::ReInit(ScViewData& rViewData) |
160 | 0 | { |
161 | 0 | pViewData = &rViewData; |
162 | 0 | pDoc = &rViewData.GetDocument(); |
163 | |
|
164 | 0 | bNoSelection=false; |
165 | 0 | bIgnoreMsg=false; |
166 | 0 | nAcceptCount=0; |
167 | 0 | nRejectCount=0; |
168 | | |
169 | | // don't call Init here (switching between views), just set link below |
170 | | // (dialog is just hidden, not deleted anymore, when switching views) |
171 | 0 | ClearView(); |
172 | 0 | UpdateView(); |
173 | |
|
174 | 0 | ScChangeTrack* pChanges = pDoc->GetChangeTrack(); |
175 | 0 | if ( pChanges ) |
176 | 0 | pChanges->SetModifiedLink( LINK( this, ScAcceptChgDlg, ChgTrackModHdl ) ); |
177 | 0 | } |
178 | | |
179 | | void ScAcceptChgDlg::Init() |
180 | 0 | { |
181 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
182 | |
|
183 | 0 | if(pChanges!=nullptr) |
184 | 0 | { |
185 | 0 | pChanges->SetModifiedLink( LINK( this, ScAcceptChgDlg,ChgTrackModHdl)); |
186 | 0 | aChangeViewSet.SetTheAuthorToShow(pChanges->GetUser()); |
187 | 0 | pTPFilter->ClearAuthors(); |
188 | 0 | const std::set<OUString>& rUserColl = pChanges->GetUserCollection(); |
189 | 0 | for (const auto& rItem : rUserColl) |
190 | 0 | pTPFilter->InsertAuthor(rItem); |
191 | 0 | } |
192 | |
|
193 | 0 | ScChangeViewSettings* pViewSettings=pDoc->GetChangeViewSettings(); |
194 | 0 | if ( pViewSettings!=nullptr ) |
195 | 0 | aChangeViewSet = *pViewSettings; |
196 | | // adjust TimeField for filter tabpage |
197 | 0 | aChangeViewSet.AdjustDateMode( *pDoc ); |
198 | |
|
199 | 0 | pTPFilter->CheckDate(aChangeViewSet.HasDate()); |
200 | |
|
201 | 0 | DateTime aEmpty(DateTime::EMPTY); |
202 | |
|
203 | 0 | DateTime aDateTime(aChangeViewSet.GetTheFirstDateTime()); |
204 | 0 | if (aDateTime != aEmpty) |
205 | 0 | { |
206 | 0 | pTPFilter->SetFirstDate(aDateTime); |
207 | 0 | pTPFilter->SetFirstTime(aDateTime); |
208 | 0 | } |
209 | 0 | aDateTime = aChangeViewSet.GetTheLastDateTime(); |
210 | 0 | if (aDateTime != aEmpty) |
211 | 0 | { |
212 | 0 | pTPFilter->SetLastDate(aDateTime); |
213 | 0 | pTPFilter->SetLastTime(aDateTime); |
214 | 0 | } |
215 | |
|
216 | 0 | pTPFilter->SetDateMode(static_cast<sal_uInt16>(aChangeViewSet.GetTheDateMode())); |
217 | 0 | pTPFilter->CheckComment(aChangeViewSet.HasComment()); |
218 | 0 | pTPFilter->SetComment(aChangeViewSet.GetTheComment()); |
219 | |
|
220 | 0 | pTPFilter->CheckAuthor(aChangeViewSet.HasAuthor()); |
221 | 0 | OUString aString=aChangeViewSet.GetTheAuthorToShow(); |
222 | 0 | if(!aString.isEmpty()) |
223 | 0 | { |
224 | 0 | pTPFilter->SelectAuthor(aString); |
225 | 0 | if(pTPFilter->GetSelectedAuthor()!=aString) |
226 | 0 | { |
227 | 0 | pTPFilter->InsertAuthor(aString); |
228 | 0 | pTPFilter->SelectAuthor(aString); |
229 | 0 | } |
230 | 0 | } |
231 | 0 | else |
232 | 0 | pTPFilter->SelectedAuthorPos(0); |
233 | |
|
234 | 0 | pTPFilter->CheckRange(aChangeViewSet.HasRange()); |
235 | |
|
236 | 0 | aRangeList=aChangeViewSet.GetTheRangeList(); |
237 | |
|
238 | 0 | if( !aChangeViewSet.GetTheRangeList().empty() ) |
239 | 0 | { |
240 | 0 | const ScRange & rRangeEntry = aChangeViewSet.GetTheRangeList().front(); |
241 | 0 | OUString aRefStr(rRangeEntry.Format(*pDoc, ScRefFlags::RANGE_ABS_3D)); |
242 | 0 | pTPFilter->SetRange(aRefStr); |
243 | 0 | } |
244 | | |
245 | | // init filter |
246 | 0 | if(!(pTPFilter->IsDate()||pTPFilter->IsRange()|| |
247 | 0 | pTPFilter->IsAuthor()||pTPFilter->IsComment())) |
248 | 0 | return; |
249 | | |
250 | 0 | pTheView->SetFilterDate(pTPFilter->IsDate()); |
251 | 0 | pTheView->SetDateTimeMode(pTPFilter->GetDateMode()); |
252 | 0 | pTheView->SetFirstDate(pTPFilter->GetFirstDate()); |
253 | 0 | pTheView->SetLastDate(pTPFilter->GetLastDate()); |
254 | 0 | pTheView->SetFirstTime(pTPFilter->GetFirstTime()); |
255 | 0 | pTheView->SetLastTime(pTPFilter->GetLastTime()); |
256 | 0 | pTheView->SetFilterAuthor(pTPFilter->IsAuthor()); |
257 | 0 | pTheView->SetAuthor(pTPFilter->GetSelectedAuthor()); |
258 | |
|
259 | 0 | pTheView->SetFilterComment(pTPFilter->IsComment()); |
260 | |
|
261 | 0 | utl::SearchParam aSearchParam( pTPFilter->GetComment(), |
262 | 0 | utl::SearchParam::SearchType::Regexp,false ); |
263 | |
|
264 | 0 | pTheView->SetCommentParams(&aSearchParam); |
265 | |
|
266 | 0 | pTheView->UpdateFilterTest(); |
267 | 0 | } |
268 | | |
269 | | void ScAcceptChgDlg::ClearView() |
270 | 0 | { |
271 | 0 | nAcceptCount=0; |
272 | 0 | nRejectCount=0; |
273 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
274 | 0 | rTreeView.all_foreach( |
275 | 0 | [&rTreeView](weld::TreeIter& rEntry) |
276 | 0 | { |
277 | 0 | ScRedlineData* pEntryData = weld::fromId<ScRedlineData*>(rTreeView.get_id(rEntry)); |
278 | 0 | delete pEntryData; |
279 | 0 | return false; |
280 | 0 | }); |
281 | 0 | rTreeView.freeze(); |
282 | 0 | rTreeView.clear(); |
283 | 0 | rTreeView.thaw(); |
284 | 0 | } |
285 | | |
286 | | OUString* ScAcceptChgDlg::MakeTypeString(ScChangeActionType eType) |
287 | 0 | { |
288 | 0 | OUString* pStr; |
289 | |
|
290 | 0 | switch(eType) |
291 | 0 | { |
292 | | |
293 | 0 | case SC_CAT_INSERT_COLS: pStr=&aStrInsertCols;break; |
294 | 0 | case SC_CAT_INSERT_ROWS: pStr=&aStrInsertRows;break; |
295 | 0 | case SC_CAT_INSERT_TABS: pStr=&aStrInsertTabs;break; |
296 | 0 | case SC_CAT_DELETE_COLS: pStr=&aStrDeleteCols;break; |
297 | 0 | case SC_CAT_DELETE_ROWS: pStr=&aStrDeleteRows;break; |
298 | 0 | case SC_CAT_DELETE_TABS: pStr=&aStrDeleteTabs;break; |
299 | 0 | case SC_CAT_MOVE: pStr=&aStrMove;break; |
300 | 0 | case SC_CAT_CONTENT: pStr=&aStrContent;break; |
301 | 0 | case SC_CAT_REJECT: pStr=&aStrReject;break; |
302 | 0 | default: pStr=&aUnknown;break; |
303 | 0 | } |
304 | 0 | return pStr; |
305 | 0 | } |
306 | | |
307 | | bool ScAcceptChgDlg::IsValidAction(const ScChangeAction* pScChangeAction) |
308 | 0 | { |
309 | 0 | if(pScChangeAction==nullptr) return false; |
310 | | |
311 | 0 | bool bFlag = false; |
312 | |
|
313 | 0 | ScRange aRef=pScChangeAction->GetBigRange().MakeRange(*pDoc); |
314 | 0 | const OUString& aUser=pScChangeAction->GetUser(); |
315 | 0 | DateTime aDateTime=pScChangeAction->GetDateTime(); |
316 | |
|
317 | 0 | ScChangeActionType eType=pScChangeAction->GetType(); |
318 | 0 | OUString aDesc; |
319 | |
|
320 | 0 | OUString aComment = pScChangeAction->GetComment().replaceAll("\n", ""); |
321 | |
|
322 | 0 | if(eType==SC_CAT_CONTENT) |
323 | 0 | { |
324 | 0 | if(!pScChangeAction->IsDialogParent()) |
325 | 0 | aDesc = pScChangeAction->GetDescription(*pDoc, true); |
326 | 0 | } |
327 | 0 | else |
328 | 0 | aDesc = pScChangeAction->GetDescription(*pDoc, !pScChangeAction->IsMasterDelete()); |
329 | |
|
330 | 0 | if (!aDesc.isEmpty()) |
331 | 0 | { |
332 | 0 | aComment += " (" + aDesc + ")"; |
333 | 0 | } |
334 | |
|
335 | 0 | if (pTheView->IsValidEntry(aUser, aDateTime, aComment)) |
336 | 0 | { |
337 | 0 | if(pTPFilter->IsRange()) |
338 | 0 | { |
339 | 0 | for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i ) |
340 | 0 | { |
341 | 0 | ScRange const & rRangeEntry = aRangeList[ i ]; |
342 | 0 | if (rRangeEntry.Intersects(aRef)) { |
343 | 0 | bFlag = true; |
344 | 0 | break; |
345 | 0 | } |
346 | 0 | } |
347 | 0 | } |
348 | 0 | else |
349 | 0 | bFlag=true; |
350 | 0 | } |
351 | |
|
352 | 0 | return bFlag; |
353 | 0 | } |
354 | | |
355 | | std::unique_ptr<weld::TreeIter> ScAcceptChgDlg::AppendChangeAction( |
356 | | const ScChangeAction* pScChangeAction, bool bCreateOnDemand, |
357 | | const weld::TreeIter* pParent, bool bDelMaster, bool bDisabled) |
358 | 0 | { |
359 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
360 | |
|
361 | 0 | if(pScChangeAction==nullptr || pChanges==nullptr) return nullptr; |
362 | | |
363 | 0 | bool bFlag = false; |
364 | |
|
365 | 0 | ScRange aRef=pScChangeAction->GetBigRange().MakeRange(*pDoc); |
366 | 0 | DateTime aDateTime=pScChangeAction->GetDateTime(); |
367 | |
|
368 | 0 | ScChangeActionType eType=pScChangeAction->GetType(); |
369 | 0 | OUString aActionString; |
370 | 0 | OUString aRefStr; |
371 | 0 | OUString aUser; |
372 | 0 | OUString aDate; |
373 | 0 | OUString aDesc; |
374 | |
|
375 | 0 | std::unique_ptr<ScRedlineData> pNewData(new ScRedlineData); |
376 | 0 | pNewData->pData=const_cast<ScChangeAction *>(pScChangeAction); |
377 | 0 | pNewData->nActionNo=pScChangeAction->GetActionNumber(); |
378 | 0 | pNewData->bIsAcceptable=pScChangeAction->IsClickable(); |
379 | 0 | pNewData->bIsRejectable=pScChangeAction->IsRejectable(); |
380 | 0 | pNewData->bDisabled=!pNewData->bIsAcceptable || bDisabled; |
381 | 0 | pNewData->aDateTime=aDateTime; |
382 | 0 | pNewData->nRow = aRef.aStart.Row(); |
383 | 0 | pNewData->nCol = aRef.aStart.Col(); |
384 | 0 | pNewData->nTable= aRef.aStart.Tab(); |
385 | |
|
386 | 0 | if(eType==SC_CAT_CONTENT) |
387 | 0 | { |
388 | 0 | if(pScChangeAction->IsDialogParent()) |
389 | 0 | { |
390 | 0 | aActionString = aStrContentWithChild; |
391 | 0 | pNewData->nInfo=RD_SPECIAL_VISCONTENT; |
392 | 0 | pNewData->bIsRejectable=false; |
393 | 0 | pNewData->bIsAcceptable=false; |
394 | 0 | } |
395 | 0 | else |
396 | 0 | { |
397 | 0 | aActionString = *MakeTypeString(eType); |
398 | 0 | aDesc = pScChangeAction->GetDescription(*pDoc, true); |
399 | 0 | } |
400 | 0 | } |
401 | 0 | else |
402 | 0 | { |
403 | 0 | aActionString = *MakeTypeString(eType); |
404 | |
|
405 | 0 | if(bDelMaster) |
406 | 0 | { |
407 | 0 | aDesc = pScChangeAction->GetDescription(*pDoc,true); |
408 | 0 | pNewData->bDisabled=true; |
409 | 0 | pNewData->bIsRejectable=false; |
410 | 0 | } |
411 | 0 | else |
412 | 0 | aDesc = pScChangeAction->GetDescription(*pDoc, !pScChangeAction->IsMasterDelete()); |
413 | |
|
414 | 0 | } |
415 | |
|
416 | 0 | aRefStr = pScChangeAction->GetRefString(*pDoc, true); |
417 | |
|
418 | 0 | bool bIsGenerated = false; |
419 | |
|
420 | 0 | if(!pChanges->IsGenerated(pScChangeAction->GetActionNumber())) |
421 | 0 | { |
422 | 0 | aUser = pScChangeAction->GetUser(); |
423 | 0 | aDate = ScGlobal::getLocaleData().getDate(aDateTime) + " " + ScGlobal::getLocaleData().getTime(aDateTime); |
424 | 0 | bIsGenerated = false; |
425 | 0 | } |
426 | 0 | else |
427 | 0 | { |
428 | 0 | bIsGenerated = true; |
429 | 0 | } |
430 | |
|
431 | 0 | OUString aComment = pScChangeAction->GetComment().replaceAll("\n", ""); |
432 | |
|
433 | 0 | if (!aDesc.isEmpty()) |
434 | 0 | { |
435 | 0 | aComment += " (" + aDesc + ")"; |
436 | 0 | } |
437 | |
|
438 | 0 | if (pTheView->IsValidEntry(aUser, aDateTime) || bIsGenerated) |
439 | 0 | { |
440 | 0 | if (pTheView->IsValidComment(aComment)) |
441 | 0 | { |
442 | 0 | if(pTPFilter->IsRange()) |
443 | 0 | { |
444 | 0 | for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i ) |
445 | 0 | { |
446 | 0 | ScRange const & rRangeEntry = aRangeList[ i ]; |
447 | 0 | if( rRangeEntry.Intersects(aRef) ) |
448 | 0 | { |
449 | 0 | bHasFilterEntry=true; |
450 | 0 | bFlag=true; |
451 | 0 | break; |
452 | 0 | } |
453 | 0 | } |
454 | 0 | } |
455 | 0 | else if(!bIsGenerated) |
456 | 0 | { |
457 | 0 | bHasFilterEntry=true; |
458 | 0 | bFlag=true; |
459 | 0 | } |
460 | 0 | } |
461 | 0 | } |
462 | |
|
463 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
464 | 0 | std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator()); |
465 | 0 | OUString sId(weld::toId(pNewData.release())); |
466 | 0 | rTreeView.insert(pParent, -1, &aActionString, &sId, nullptr, nullptr, bCreateOnDemand, xEntry.get()); |
467 | 0 | rTreeView.set_text( *xEntry, aRefStr, 1); |
468 | 0 | if (!aUser.isEmpty()) |
469 | 0 | rTreeView.set_text( *xEntry, aUser, 2); |
470 | 0 | if (!aDate.isEmpty()) |
471 | 0 | rTreeView.set_text( *xEntry, aDate, 3); |
472 | 0 | if (!aComment.isEmpty()) |
473 | 0 | rTreeView.set_text( *xEntry, aComment, 4); |
474 | 0 | if (!bFlag && bUseColor && !pParent) |
475 | 0 | { |
476 | 0 | rTreeView.set_font_color(*xEntry, COL_LIGHTBLUE); |
477 | 0 | } |
478 | 0 | else if (bFlag && bUseColor && pParent) |
479 | 0 | { |
480 | 0 | rTreeView.set_font_color(*xEntry, COL_GREEN); |
481 | |
|
482 | 0 | std::unique_ptr<weld::TreeIter> xExpEntry(rTreeView.make_iterator(pParent)); |
483 | |
|
484 | 0 | while (!rTreeView.get_row_expanded(*xExpEntry)) |
485 | 0 | { |
486 | 0 | if (rTreeView.get_iter_depth(*xExpEntry)) |
487 | 0 | rTreeView.expand_row(*xExpEntry); |
488 | |
|
489 | 0 | if (!rTreeView.iter_parent(*xExpEntry)) |
490 | 0 | break; |
491 | 0 | } |
492 | 0 | } |
493 | 0 | return xEntry; |
494 | 0 | } |
495 | | |
496 | | std::unique_ptr<weld::TreeIter> ScAcceptChgDlg::AppendFilteredAction( |
497 | | const ScChangeAction* pScChangeAction, ScChangeActionState eState, |
498 | | bool bCreateOnDemand, |
499 | | const weld::TreeIter* pParent, bool bDelMaster, bool bDisabled) |
500 | 0 | { |
501 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
502 | |
|
503 | 0 | if(pScChangeAction==nullptr || pChanges==nullptr) return nullptr; |
504 | | |
505 | 0 | bool bIsGenerated = pChanges->IsGenerated(pScChangeAction->GetActionNumber()); |
506 | |
|
507 | 0 | bool bFlag = false; |
508 | |
|
509 | 0 | ScRange aRef=pScChangeAction->GetBigRange().MakeRange(*pDoc); |
510 | 0 | const OUString& aUser=pScChangeAction->GetUser(); |
511 | 0 | DateTime aDateTime=pScChangeAction->GetDateTime(); |
512 | |
|
513 | 0 | if (pTheView->IsValidEntry(aUser, aDateTime) || bIsGenerated) |
514 | 0 | { |
515 | 0 | if(pTPFilter->IsRange()) |
516 | 0 | { |
517 | 0 | for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i ) |
518 | 0 | { |
519 | 0 | ScRange const & rRangeEntry=aRangeList[ i ]; |
520 | 0 | if( rRangeEntry.Intersects(aRef) ) |
521 | 0 | { |
522 | 0 | if( pScChangeAction->GetState()==eState ) |
523 | 0 | bFlag = true; |
524 | 0 | break; |
525 | 0 | } |
526 | 0 | } |
527 | 0 | } |
528 | 0 | else if(pScChangeAction->GetState()==eState && !bIsGenerated) |
529 | 0 | bFlag = true; |
530 | 0 | } |
531 | |
|
532 | 0 | std::unique_ptr<weld::TreeIter> xEntry; |
533 | 0 | if(bFlag) |
534 | 0 | { |
535 | 0 | ScChangeActionType eType=pScChangeAction->GetType(); |
536 | 0 | OUString aActionString; |
537 | 0 | OUString aDesc; |
538 | |
|
539 | 0 | std::unique_ptr<ScRedlineData> pNewData(new ScRedlineData); |
540 | 0 | pNewData->pData=const_cast<ScChangeAction *>(pScChangeAction); |
541 | 0 | pNewData->nActionNo=pScChangeAction->GetActionNumber(); |
542 | 0 | pNewData->bIsAcceptable=pScChangeAction->IsClickable(); |
543 | 0 | pNewData->bIsRejectable=pScChangeAction->IsRejectable(); |
544 | 0 | pNewData->bDisabled=!pNewData->bIsAcceptable || bDisabled; |
545 | 0 | pNewData->aDateTime=aDateTime; |
546 | 0 | pNewData->nRow = aRef.aStart.Row(); |
547 | 0 | pNewData->nCol = aRef.aStart.Col(); |
548 | 0 | pNewData->nTable= aRef.aStart.Tab(); |
549 | |
|
550 | 0 | if(eType==SC_CAT_CONTENT) |
551 | 0 | { |
552 | 0 | if(pScChangeAction->IsDialogParent()) |
553 | 0 | { |
554 | 0 | aActionString=aStrContentWithChild; |
555 | 0 | pNewData->nInfo=RD_SPECIAL_VISCONTENT; |
556 | 0 | pNewData->bIsRejectable=false; |
557 | 0 | pNewData->bIsAcceptable=false; |
558 | 0 | } |
559 | 0 | else |
560 | 0 | { |
561 | 0 | aActionString=*MakeTypeString(eType); |
562 | 0 | aDesc = pScChangeAction->GetDescription(*pDoc, true); |
563 | 0 | } |
564 | 0 | } |
565 | 0 | else |
566 | 0 | { |
567 | 0 | aActionString=*MakeTypeString(eType); |
568 | |
|
569 | 0 | if(bDelMaster) |
570 | 0 | { |
571 | 0 | aDesc = pScChangeAction->GetDescription(*pDoc,true); |
572 | 0 | pNewData->bDisabled=true; |
573 | 0 | pNewData->bIsRejectable=false; |
574 | 0 | } |
575 | 0 | else |
576 | 0 | aDesc = pScChangeAction->GetDescription(*pDoc,!pScChangeAction->IsMasterDelete()); |
577 | |
|
578 | 0 | } |
579 | | |
580 | |
|
581 | 0 | OUString aComment = pScChangeAction->GetComment().replaceAll("\n", ""); |
582 | 0 | if (!aDesc.isEmpty()) |
583 | 0 | { |
584 | 0 | aComment += " (" + aDesc + ")"; |
585 | 0 | } |
586 | 0 | if (pTheView->IsValidComment(aComment)) |
587 | 0 | { |
588 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
589 | 0 | xEntry = rTreeView.make_iterator(); |
590 | 0 | OUString sId(weld::toId(pNewData.release())); |
591 | 0 | rTreeView.insert(pParent, -1, &aActionString, &sId, nullptr, nullptr, bCreateOnDemand, xEntry.get()); |
592 | |
|
593 | 0 | OUString aRefStr = pScChangeAction->GetRefString(*pDoc, true); |
594 | 0 | rTreeView.set_text(*xEntry, aRefStr, 1); |
595 | |
|
596 | 0 | if (!bIsGenerated) |
597 | 0 | { |
598 | 0 | rTreeView.set_text(*xEntry, aUser, 2); |
599 | 0 | OUString sDate = ScGlobal::getLocaleData().getDate(aDateTime) + " " + ScGlobal::getLocaleData().getTime(aDateTime); |
600 | 0 | rTreeView.set_text(*xEntry, sDate, 3); |
601 | 0 | } |
602 | |
|
603 | 0 | rTreeView.set_text(*xEntry, aComment, 4); |
604 | 0 | } |
605 | 0 | } |
606 | 0 | return xEntry; |
607 | 0 | } |
608 | | |
609 | | std::unique_ptr<weld::TreeIter> ScAcceptChgDlg::InsertChangeActionContent(const ScChangeActionContent* pScChangeAction, |
610 | | const weld::TreeIter& rParent, sal_uLong nSpecial) |
611 | 0 | { |
612 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
613 | |
|
614 | 0 | if(pScChangeAction==nullptr || pChanges==nullptr) return nullptr; |
615 | | |
616 | 0 | bool bIsGenerated = pChanges->IsGenerated(pScChangeAction->GetActionNumber()); |
617 | |
|
618 | 0 | bool bFlag = false; |
619 | |
|
620 | 0 | ScRange aRef=pScChangeAction->GetBigRange().MakeRange(*pDoc); |
621 | 0 | OUString aUser=pScChangeAction->GetUser(); |
622 | 0 | DateTime aDateTime=pScChangeAction->GetDateTime(); |
623 | |
|
624 | 0 | if (pTheView->IsValidEntry(aUser, aDateTime) || bIsGenerated) |
625 | 0 | { |
626 | 0 | if(pTPFilter->IsRange()) |
627 | 0 | { |
628 | 0 | for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i ) |
629 | 0 | { |
630 | 0 | ScRange const & rRangeEntry = aRangeList[ i ]; |
631 | 0 | if( rRangeEntry.Intersects(aRef) ) |
632 | 0 | { |
633 | 0 | bFlag=true; |
634 | 0 | break; |
635 | 0 | } |
636 | 0 | } |
637 | 0 | } |
638 | 0 | else if(!bIsGenerated) |
639 | 0 | bFlag=true; |
640 | 0 | } |
641 | |
|
642 | 0 | OUString aContent; |
643 | 0 | OUString aRefStr; |
644 | 0 | OUString aDate; |
645 | 0 | OUString aDesc; |
646 | |
|
647 | 0 | if(nSpecial==RD_SPECIAL_CONTENT) |
648 | 0 | { |
649 | 0 | aContent = pScChangeAction->GetOldString(*pDoc); |
650 | 0 | if (aContent.isEmpty()) |
651 | 0 | aContent = aStrEmpty; |
652 | 0 | aDesc = aStrChildOrgContent + ": " + aContent; |
653 | 0 | } |
654 | 0 | else |
655 | 0 | { |
656 | 0 | const OUString aTmp( pScChangeAction->GetNewString(*pDoc)); |
657 | 0 | if (aTmp.isEmpty()) |
658 | 0 | aContent = aStrEmpty; |
659 | 0 | else |
660 | 0 | aContent = "\'" + aTmp + "\'"; |
661 | 0 | aDesc = aStrChildContent + aContent; |
662 | 0 | } |
663 | |
|
664 | 0 | aRefStr = pScChangeAction->GetRefString(*pDoc, true); |
665 | |
|
666 | 0 | if(!bIsGenerated) |
667 | 0 | { |
668 | | // aUser is kept. |
669 | 0 | aDate = ScGlobal::getLocaleData().getDate(aDateTime) + " " + ScGlobal::getLocaleData().getTime(aDateTime); |
670 | 0 | } |
671 | 0 | else |
672 | 0 | { |
673 | 0 | aUser.clear(); |
674 | 0 | } |
675 | |
|
676 | 0 | OUString aComment = pScChangeAction->GetComment().replaceAll("\n", ""); |
677 | |
|
678 | 0 | if(!aDesc.isEmpty()) |
679 | 0 | { |
680 | 0 | aComment += " (" + aDesc + ")"; |
681 | 0 | } |
682 | |
|
683 | 0 | std::unique_ptr<ScRedlineData> pNewData(new ScRedlineData); |
684 | 0 | pNewData->nInfo=nSpecial; |
685 | 0 | pNewData->pData=const_cast<ScChangeActionContent *>(pScChangeAction); |
686 | 0 | pNewData->nActionNo=pScChangeAction->GetActionNumber(); |
687 | 0 | pNewData->bIsAcceptable=pScChangeAction->IsClickable(); |
688 | 0 | pNewData->bIsRejectable=false; |
689 | 0 | pNewData->bDisabled=!pNewData->bIsAcceptable; |
690 | 0 | pNewData->aDateTime=aDateTime; |
691 | 0 | pNewData->nRow = aRef.aStart.Row(); |
692 | 0 | pNewData->nCol = aRef.aStart.Col(); |
693 | 0 | pNewData->nTable= aRef.aStart.Tab(); |
694 | |
|
695 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
696 | 0 | std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator()); |
697 | 0 | OUString sId(weld::toId(pNewData.release())); |
698 | 0 | rTreeView.insert(&rParent, -1, &aContent, &sId, nullptr, nullptr, false, xEntry.get()); |
699 | 0 | rTreeView.set_text( *xEntry, aRefStr, 1); |
700 | 0 | if (!aUser.isEmpty()) |
701 | 0 | rTreeView.set_text( *xEntry, aUser, 2); |
702 | 0 | if (!aDate.isEmpty()) |
703 | 0 | rTreeView.set_text( *xEntry, aDate, 3); |
704 | 0 | if (!aComment.isEmpty()) |
705 | 0 | rTreeView.set_text( *xEntry, aComment, 4); |
706 | 0 | if (pTheView->IsValidComment(aComment) && bFlag) |
707 | 0 | bHasFilterEntry=true; |
708 | 0 | else |
709 | 0 | { |
710 | 0 | rTreeView.set_font_color(*xEntry, COL_LIGHTBLUE); |
711 | 0 | } |
712 | 0 | return xEntry; |
713 | 0 | } |
714 | | |
715 | | void ScAcceptChgDlg::UpdateView() |
716 | 0 | { |
717 | 0 | std::unique_ptr<weld::TreeIter> xParent; |
718 | 0 | ScChangeTrack* pChanges=nullptr; |
719 | 0 | const ScChangeAction* pScChangeAction=nullptr; |
720 | 0 | m_xDialog->set_busy_cursor(true); |
721 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
722 | 0 | rTreeView.freeze(); |
723 | 0 | bool bFilterFlag = pTPFilter->IsDate() || pTPFilter->IsRange() || |
724 | 0 | pTPFilter->IsAuthor() || pTPFilter->IsComment(); |
725 | |
|
726 | 0 | bUseColor = bFilterFlag; |
727 | |
|
728 | 0 | pChanges=pDoc->GetChangeTrack(); |
729 | 0 | if(pChanges!=nullptr) |
730 | 0 | pScChangeAction=pChanges->GetFirst(); |
731 | 0 | bool bTheFlag = false; |
732 | |
|
733 | 0 | while(pScChangeAction!=nullptr) |
734 | 0 | { |
735 | 0 | bHasFilterEntry=false; |
736 | 0 | switch (pScChangeAction->GetState()) |
737 | 0 | { |
738 | 0 | case SC_CAS_VIRGIN: |
739 | |
|
740 | 0 | if (pScChangeAction->IsDialogRoot()) |
741 | 0 | { |
742 | 0 | bool bOnDemandChildren = !bFilterFlag && pScChangeAction->IsDialogParent(); |
743 | 0 | if (pScChangeAction->IsDialogParent()) |
744 | 0 | xParent = AppendChangeAction(pScChangeAction, bOnDemandChildren); |
745 | 0 | else |
746 | 0 | xParent = AppendFilteredAction(pScChangeAction, SC_CAS_VIRGIN, bOnDemandChildren); |
747 | 0 | } |
748 | 0 | else |
749 | 0 | xParent.reset(); |
750 | |
|
751 | 0 | bTheFlag=true; |
752 | 0 | break; |
753 | | |
754 | 0 | case SC_CAS_ACCEPTED: |
755 | 0 | xParent.reset(); |
756 | 0 | nAcceptCount++; |
757 | 0 | break; |
758 | | |
759 | 0 | case SC_CAS_REJECTED: |
760 | 0 | xParent.reset(); |
761 | 0 | nRejectCount++; |
762 | 0 | break; |
763 | 0 | } |
764 | | |
765 | 0 | if (xParent && pScChangeAction->IsDialogParent() && bFilterFlag) |
766 | 0 | { |
767 | 0 | bool bTestFlag = bHasFilterEntry; |
768 | 0 | bHasFilterEntry=false; |
769 | 0 | if (Expand(pChanges, pScChangeAction, *xParent, !bTestFlag) && !bTestFlag) |
770 | 0 | rTreeView.remove(*xParent); |
771 | 0 | } |
772 | |
|
773 | 0 | pScChangeAction=pScChangeAction->GetNext(); |
774 | 0 | } |
775 | | |
776 | 0 | if( bTheFlag && (!pDoc->IsDocEditable() || pChanges->IsProtected()) ) |
777 | 0 | bTheFlag=false; |
778 | |
|
779 | 0 | m_rTPView.EnableAccept(bTheFlag); |
780 | 0 | m_rTPView.EnableAcceptAll(bTheFlag); |
781 | 0 | m_rTPView.EnableReject(bTheFlag); |
782 | 0 | m_rTPView.EnableRejectAll(bTheFlag); |
783 | |
|
784 | 0 | if (nAcceptCount>0) |
785 | 0 | rTreeView.insert(nullptr, -1, &aStrAllAccepted, nullptr, nullptr, nullptr, true, nullptr); |
786 | 0 | if (nRejectCount>0) |
787 | 0 | rTreeView.insert(nullptr, -1, &aStrAllRejected, nullptr, nullptr, nullptr, true, nullptr); |
788 | 0 | rTreeView.thaw(); |
789 | 0 | m_xDialog->set_busy_cursor(false); |
790 | 0 | std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator()); |
791 | 0 | if (rTreeView.get_iter_first(*xEntry)) |
792 | 0 | rTreeView.select(*xEntry); |
793 | 0 | } |
794 | | |
795 | | IMPL_LINK_NOARG(ScAcceptChgDlg, RefHandle, SvxTPFilter*, void) |
796 | 0 | { |
797 | 0 | sal_uInt16 nId =ScSimpleRefDlgWrapper::GetChildWindowId(); |
798 | |
|
799 | 0 | ScModule::get()->SetRefDialog(nId, true); |
800 | |
|
801 | 0 | SfxViewFrame& rViewFrm = pViewData->GetViewShell()->GetViewFrame(); |
802 | 0 | ScSimpleRefDlgWrapper* pWnd = static_cast<ScSimpleRefDlgWrapper*>(rViewFrm.GetChildWindow( nId )); |
803 | |
|
804 | 0 | if(pWnd!=nullptr) |
805 | 0 | { |
806 | 0 | sal_uInt16 nAcceptId=ScAcceptChgDlgWrapper::GetChildWindowId(); |
807 | 0 | rViewFrm.ShowChildWindow(nAcceptId,false); |
808 | 0 | pWnd->SetCloseHdl(LINK( this, ScAcceptChgDlg,RefInfoHandle)); |
809 | 0 | pWnd->SetRefString(pTPFilter->GetRange()); |
810 | 0 | ScSimpleRefDlgWrapper::SetAutoReOpen(false); |
811 | 0 | auto xWin = pWnd->GetController(); |
812 | 0 | m_xDialog->hide(); |
813 | 0 | xWin->set_title(m_xDialog->get_title()); |
814 | 0 | pWnd->StartRefInput(); |
815 | 0 | } |
816 | 0 | } |
817 | | |
818 | | IMPL_LINK( ScAcceptChgDlg, RefInfoHandle, const OUString*, pResult, void) |
819 | 0 | { |
820 | 0 | sal_uInt16 nId = ScAcceptChgDlgWrapper::GetChildWindowId(); |
821 | |
|
822 | 0 | ScSimpleRefDlgWrapper::SetAutoReOpen(true); |
823 | |
|
824 | 0 | SfxViewFrame& rViewFrm = pViewData->GetViewShell()->GetViewFrame(); |
825 | 0 | if (pResult) |
826 | 0 | { |
827 | 0 | pTPFilter->SetRange(*pResult); |
828 | 0 | FilterHandle(pTPFilter); |
829 | |
|
830 | 0 | rViewFrm.ShowChildWindow(nId); |
831 | 0 | } |
832 | 0 | else |
833 | 0 | { |
834 | 0 | rViewFrm.SetChildWindow(nId, false); |
835 | 0 | } |
836 | 0 | } |
837 | | |
838 | | IMPL_LINK( ScAcceptChgDlg, FilterHandle, SvxTPFilter*, pRef, void ) |
839 | 0 | { |
840 | 0 | if(pRef!=nullptr) |
841 | 0 | { |
842 | 0 | ClearView(); |
843 | 0 | aRangeList.RemoveAll(); |
844 | 0 | aRangeList.Parse(pTPFilter->GetRange(), *pDoc); |
845 | 0 | UpdateView(); |
846 | 0 | } |
847 | 0 | } |
848 | | |
849 | | IMPL_LINK( ScAcceptChgDlg, RejectHandle, SvxTPView*, pRef, void ) |
850 | 0 | { |
851 | 0 | m_xDialog->set_busy_cursor(true); |
852 | |
|
853 | 0 | bIgnoreMsg=true; |
854 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
855 | |
|
856 | 0 | if(pRef!=nullptr) |
857 | 0 | { |
858 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
859 | 0 | rTreeView.selected_foreach([this, pChanges, &rTreeView](weld::TreeIter& rEntry){ |
860 | 0 | ScRedlineData* pEntryData = weld::fromId<ScRedlineData*>(rTreeView.get_id(rEntry)); |
861 | 0 | if (pEntryData) |
862 | 0 | { |
863 | 0 | ScChangeAction* pScChangeAction= static_cast<ScChangeAction*>(pEntryData->pData); |
864 | 0 | if (pScChangeAction->GetType()==SC_CAT_INSERT_TABS) |
865 | 0 | pViewData->SetTabNo(0); |
866 | 0 | pChanges->Reject(pScChangeAction); |
867 | 0 | } |
868 | 0 | return false; |
869 | 0 | }); |
870 | 0 | ScDocShell* pDocSh=pViewData->GetDocShell(); |
871 | 0 | pDocSh->PostPaintExtras(); |
872 | 0 | pDocSh->PostPaintGridAll(); |
873 | 0 | pDocSh->GetUndoManager()->Clear(); |
874 | 0 | pDocSh->SetDocumentModified(); |
875 | 0 | ClearView(); |
876 | 0 | UpdateView(); |
877 | 0 | } |
878 | |
|
879 | 0 | m_xDialog->set_busy_cursor(false); |
880 | |
|
881 | 0 | bIgnoreMsg=false; |
882 | 0 | } |
883 | | IMPL_LINK( ScAcceptChgDlg, AcceptHandle, SvxTPView*, pRef, void ) |
884 | 0 | { |
885 | 0 | m_xDialog->set_busy_cursor(true); |
886 | |
|
887 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
888 | 0 | bIgnoreMsg=true; |
889 | 0 | if(pRef!=nullptr) |
890 | 0 | { |
891 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
892 | 0 | rTreeView.selected_foreach([pChanges, &rTreeView](weld::TreeIter& rEntry) { |
893 | 0 | ScRedlineData *pEntryData = weld::fromId<ScRedlineData*>(rTreeView.get_id(rEntry)); |
894 | 0 | if (pEntryData) |
895 | 0 | { |
896 | 0 | ScChangeAction* pScChangeAction= |
897 | 0 | static_cast<ScChangeAction*>(pEntryData->pData); |
898 | 0 | if(pScChangeAction->GetType()==SC_CAT_CONTENT) |
899 | 0 | { |
900 | 0 | if(pEntryData->nInfo==RD_SPECIAL_CONTENT) |
901 | 0 | pChanges->SelectContent(pScChangeAction,true); |
902 | 0 | else |
903 | 0 | pChanges->SelectContent(pScChangeAction); |
904 | 0 | } |
905 | 0 | else |
906 | 0 | pChanges->Accept(pScChangeAction); |
907 | 0 | } |
908 | 0 | return false; |
909 | 0 | }); |
910 | 0 | ScDocShell* pDocSh=pViewData->GetDocShell(); |
911 | 0 | pDocSh->PostPaintExtras(); |
912 | 0 | pDocSh->PostPaintGridAll(); |
913 | 0 | pDocSh->SetDocumentModified(); |
914 | 0 | ClearView(); |
915 | 0 | UpdateView(); |
916 | 0 | } |
917 | 0 | m_xDialog->set_busy_cursor(false); |
918 | 0 | bIgnoreMsg=false; |
919 | 0 | } |
920 | | |
921 | | void ScAcceptChgDlg::RejectFiltered() |
922 | 0 | { |
923 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
924 | 0 | const ScChangeAction* pScChangeAction=nullptr; |
925 | |
|
926 | 0 | if(pChanges!=nullptr) |
927 | 0 | { |
928 | 0 | pScChangeAction=pChanges->GetLast(); |
929 | 0 | } |
930 | |
|
931 | 0 | while(pScChangeAction!=nullptr) |
932 | 0 | { |
933 | 0 | if(pScChangeAction->IsDialogRoot()) |
934 | 0 | if(IsValidAction(pScChangeAction)) |
935 | 0 | pChanges->Reject(const_cast<ScChangeAction*>(pScChangeAction)); |
936 | |
|
937 | 0 | pScChangeAction=pScChangeAction->GetPrev(); |
938 | 0 | } |
939 | 0 | } |
940 | | void ScAcceptChgDlg::AcceptFiltered() |
941 | 0 | { |
942 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
943 | 0 | const ScChangeAction* pScChangeAction=nullptr; |
944 | |
|
945 | 0 | if(pChanges!=nullptr) |
946 | 0 | pScChangeAction=pChanges->GetLast(); |
947 | |
|
948 | 0 | while(pScChangeAction!=nullptr) |
949 | 0 | { |
950 | 0 | if(pScChangeAction->IsDialogRoot()) |
951 | 0 | if(IsValidAction(pScChangeAction)) |
952 | 0 | pChanges->Accept(const_cast<ScChangeAction*>(pScChangeAction)); |
953 | |
|
954 | 0 | pScChangeAction=pScChangeAction->GetPrev(); |
955 | 0 | } |
956 | 0 | } |
957 | | |
958 | | IMPL_LINK_NOARG(ScAcceptChgDlg, RejectAllHandle, SvxTPView*, void) |
959 | 0 | { |
960 | 0 | m_xDialog->set_busy_cursor(true); |
961 | 0 | bIgnoreMsg=true; |
962 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
963 | 0 | if(pChanges!=nullptr) |
964 | 0 | { |
965 | 0 | if(pTPFilter->IsDate()||pTPFilter->IsAuthor()||pTPFilter->IsRange()||pTPFilter->IsComment()) |
966 | 0 | RejectFiltered(); |
967 | 0 | else |
968 | 0 | pChanges->RejectAll(); |
969 | |
|
970 | 0 | pViewData->SetTabNo(0); |
971 | |
|
972 | 0 | ScDocShell* pDocSh=pViewData->GetDocShell(); |
973 | 0 | pDocSh->PostPaintExtras(); |
974 | 0 | pDocSh->PostPaintGridAll(); |
975 | 0 | pDocSh->GetUndoManager()->Clear(); |
976 | 0 | pDocSh->SetDocumentModified(); |
977 | 0 | ClearView(); |
978 | 0 | UpdateView(); |
979 | 0 | } |
980 | 0 | m_xDialog->set_busy_cursor(false); |
981 | |
|
982 | 0 | bIgnoreMsg=false; |
983 | 0 | } |
984 | | |
985 | | IMPL_LINK_NOARG(ScAcceptChgDlg, AcceptAllHandle, SvxTPView*, void) |
986 | 0 | { |
987 | 0 | m_xDialog->set_busy_cursor(true); |
988 | |
|
989 | 0 | bIgnoreMsg=true; |
990 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
991 | 0 | if(pChanges!=nullptr) |
992 | 0 | { |
993 | 0 | if(pTPFilter->IsDate()||pTPFilter->IsAuthor()||pTPFilter->IsRange()||pTPFilter->IsComment()) |
994 | 0 | AcceptFiltered(); |
995 | 0 | else |
996 | 0 | pChanges->AcceptAll(); |
997 | |
|
998 | 0 | ScDocShell* pDocSh=pViewData->GetDocShell(); |
999 | 0 | pDocSh->PostPaintExtras(); |
1000 | 0 | pDocSh->PostPaintGridAll(); |
1001 | 0 | pDocSh->SetDocumentModified(); |
1002 | 0 | ClearView(); |
1003 | 0 | UpdateView(); |
1004 | 0 | } |
1005 | 0 | bIgnoreMsg=false; |
1006 | |
|
1007 | 0 | m_xDialog->set_busy_cursor(false); |
1008 | 0 | } |
1009 | | |
1010 | | IMPL_LINK_NOARG(ScAcceptChgDlg, SelectHandle, weld::TreeView&, void) |
1011 | 0 | { |
1012 | 0 | if (!bNoSelection) |
1013 | 0 | aSelectionIdle.Start(); |
1014 | |
|
1015 | 0 | bNoSelection=false; |
1016 | 0 | } |
1017 | | |
1018 | | void ScAcceptChgDlg::GetDependents(const ScChangeAction* pScChangeAction, |
1019 | | ScChangeActionMap& aActionMap, |
1020 | | const weld::TreeIter& rEntry) |
1021 | 0 | { |
1022 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
1023 | |
|
1024 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1025 | 0 | std::unique_ptr<weld::TreeIter> xParent(rTreeView.make_iterator(&rEntry)); |
1026 | 0 | if (rTreeView.iter_parent(*xParent)) |
1027 | 0 | { |
1028 | 0 | ScRedlineData* pParentData = weld::fromId<ScRedlineData*>(rTreeView.get_id(*xParent)); |
1029 | 0 | ScChangeAction* pParentAction=static_cast<ScChangeAction*>(pParentData->pData); |
1030 | |
|
1031 | 0 | if(pParentAction!=pScChangeAction) |
1032 | 0 | pChanges->GetDependents(const_cast<ScChangeAction*>(pScChangeAction), |
1033 | 0 | aActionMap,pScChangeAction->IsMasterDelete()); |
1034 | 0 | else |
1035 | 0 | pChanges->GetDependents( const_cast<ScChangeAction*>(pScChangeAction), |
1036 | 0 | aActionMap ); |
1037 | 0 | } |
1038 | 0 | else |
1039 | 0 | pChanges->GetDependents(const_cast<ScChangeAction*>(pScChangeAction), |
1040 | 0 | aActionMap, pScChangeAction->IsMasterDelete() ); |
1041 | 0 | } |
1042 | | |
1043 | | bool ScAcceptChgDlg::InsertContentChildren(ScChangeActionMap* pActionMap, const weld::TreeIter& rParent) |
1044 | 0 | { |
1045 | 0 | bool bTheTestFlag = true; |
1046 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1047 | 0 | ScRedlineData* pEntryData = weld::fromId<ScRedlineData*>(rTreeView.get_id(rParent)); |
1048 | 0 | const ScChangeAction* pScChangeAction = static_cast<ScChangeAction*>(pEntryData->pData); |
1049 | 0 | bool bParentInserted = false; |
1050 | | // If the parent is a MatrixOrigin then place it in the right order before |
1051 | | // the MatrixReferences. Also if it is the first content change at this |
1052 | | // position don't insert the first dependent MatrixReference as the special |
1053 | | // content (original value) but insert the predecessor of the MatrixOrigin |
1054 | | // itself instead. |
1055 | 0 | if ( pScChangeAction->GetType() == SC_CAT_CONTENT && |
1056 | 0 | static_cast<const ScChangeActionContent*>(pScChangeAction)->IsMatrixOrigin() ) |
1057 | 0 | { |
1058 | 0 | pActionMap->insert( ::std::make_pair( pScChangeAction->GetActionNumber(), |
1059 | 0 | const_cast<ScChangeAction*>( pScChangeAction ) ) ); |
1060 | 0 | bParentInserted = true; |
1061 | 0 | } |
1062 | |
|
1063 | 0 | ScChangeActionMap::iterator itChangeAction = std::find_if(pActionMap->begin(), pActionMap->end(), |
1064 | 0 | [](const std::pair<sal_uLong, ScChangeAction*>& rEntry) { return rEntry.second->GetState() == SC_CAS_VIRGIN; }); |
1065 | |
|
1066 | 0 | if( itChangeAction == pActionMap->end() ) |
1067 | 0 | return true; |
1068 | | |
1069 | 0 | std::unique_ptr<weld::TreeIter> xOriginal = InsertChangeActionContent( |
1070 | 0 | dynamic_cast<const ScChangeActionContent*>( itChangeAction->second ), |
1071 | 0 | rParent, RD_SPECIAL_CONTENT ); |
1072 | |
|
1073 | 0 | if (xOriginal) |
1074 | 0 | { |
1075 | 0 | bTheTestFlag=false; |
1076 | 0 | ScRedlineData* pParentData = weld::fromId<ScRedlineData*>(rTreeView.get_id(*xOriginal)); |
1077 | 0 | pParentData->pData=const_cast<ScChangeAction *>(pScChangeAction); |
1078 | 0 | pParentData->nActionNo=pScChangeAction->GetActionNumber(); |
1079 | 0 | pParentData->bIsAcceptable=pScChangeAction->IsRejectable(); // select old value |
1080 | 0 | pParentData->bIsRejectable=false; |
1081 | 0 | pParentData->bDisabled=false; |
1082 | 0 | } |
1083 | 0 | while( itChangeAction != pActionMap->end() ) |
1084 | 0 | { |
1085 | 0 | if( itChangeAction->second->GetState() == SC_CAS_VIRGIN ) |
1086 | 0 | { |
1087 | 0 | std::unique_ptr<weld::TreeIter> xEntry = |
1088 | 0 | InsertChangeActionContent( dynamic_cast<const ScChangeActionContent*>( itChangeAction->second ), |
1089 | 0 | rParent, RD_SPECIAL_NONE ); |
1090 | |
|
1091 | 0 | if (xEntry) |
1092 | 0 | bTheTestFlag=false; |
1093 | 0 | } |
1094 | 0 | ++itChangeAction; |
1095 | 0 | } |
1096 | |
|
1097 | 0 | if ( !bParentInserted ) |
1098 | 0 | { |
1099 | 0 | std::unique_ptr<weld::TreeIter> xEntry = |
1100 | 0 | InsertChangeActionContent(static_cast<const ScChangeActionContent*>( |
1101 | 0 | pScChangeAction),rParent,RD_SPECIAL_NONE); |
1102 | |
|
1103 | 0 | if (xEntry) |
1104 | 0 | { |
1105 | 0 | bTheTestFlag=false; |
1106 | 0 | ScRedlineData* pParentData = weld::fromId<ScRedlineData*>(rTreeView.get_id(*xEntry)); |
1107 | 0 | pParentData->pData=const_cast<ScChangeAction *>(pScChangeAction); |
1108 | 0 | pParentData->nActionNo=pScChangeAction->GetActionNumber(); |
1109 | 0 | pParentData->bIsAcceptable=pScChangeAction->IsClickable(); |
1110 | 0 | pParentData->bIsRejectable=false; |
1111 | 0 | pParentData->bDisabled=false; |
1112 | 0 | } |
1113 | 0 | } |
1114 | |
|
1115 | 0 | return bTheTestFlag; |
1116 | 0 | } |
1117 | | |
1118 | | bool ScAcceptChgDlg::InsertAcceptedORejected(const weld::TreeIter& rParent) |
1119 | 0 | { |
1120 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
1121 | 0 | bool bTheTestFlag = true; |
1122 | |
|
1123 | 0 | ScChangeActionState eState = SC_CAS_VIRGIN; |
1124 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1125 | 0 | OUString aString = rTreeView.get_text(rParent, 0); |
1126 | 0 | OUString a2String = aString.copy(0, aStrAllAccepted.getLength()); |
1127 | 0 | if (a2String == aStrAllAccepted) |
1128 | 0 | eState=SC_CAS_ACCEPTED; |
1129 | 0 | else |
1130 | 0 | { |
1131 | 0 | a2String = aString.copy(0, aStrAllRejected.getLength()); |
1132 | 0 | if (a2String == aStrAllRejected) |
1133 | 0 | eState=SC_CAS_REJECTED; |
1134 | 0 | } |
1135 | |
|
1136 | 0 | ScChangeAction* pScChangeAction = pChanges->GetFirst(); |
1137 | 0 | while (pScChangeAction) |
1138 | 0 | { |
1139 | 0 | if (pScChangeAction->GetState()==eState && |
1140 | 0 | AppendFilteredAction(pScChangeAction, eState, false, &rParent)) |
1141 | 0 | bTheTestFlag=false; |
1142 | 0 | pScChangeAction=pScChangeAction->GetNext(); |
1143 | 0 | } |
1144 | 0 | return bTheTestFlag; |
1145 | 0 | } |
1146 | | |
1147 | | bool ScAcceptChgDlg::InsertChildren(ScChangeActionMap* pActionMap, const weld::TreeIter& rParent) |
1148 | 0 | { |
1149 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
1150 | 0 | bool bTheTestFlag = true; |
1151 | |
|
1152 | 0 | for( const auto& rChangeAction : *pActionMap ) |
1153 | 0 | { |
1154 | 0 | std::unique_ptr<weld::TreeIter> xEntry = AppendChangeAction(rChangeAction.second, false, &rParent, false, true); |
1155 | |
|
1156 | 0 | if (xEntry) |
1157 | 0 | { |
1158 | 0 | bTheTestFlag=false; |
1159 | |
|
1160 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1161 | 0 | ScRedlineData* pEntryData = weld::fromId<ScRedlineData*>(rTreeView.get_id(*xEntry)); |
1162 | 0 | pEntryData->bIsRejectable=false; |
1163 | 0 | pEntryData->bIsAcceptable=false; |
1164 | 0 | pEntryData->bDisabled=true; |
1165 | |
|
1166 | 0 | if (rChangeAction.second->IsDialogParent()) |
1167 | 0 | Expand(pChanges, rChangeAction.second, *xEntry); |
1168 | 0 | } |
1169 | 0 | } |
1170 | 0 | return bTheTestFlag; |
1171 | 0 | } |
1172 | | |
1173 | | bool ScAcceptChgDlg::InsertDeletedChildren(const ScChangeAction* pScChangeAction, |
1174 | | ScChangeActionMap* pActionMap, const weld::TreeIter& rParent) |
1175 | 0 | { |
1176 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
1177 | 0 | bool bTheTestFlag = true; |
1178 | 0 | std::unique_ptr<weld::TreeIter> xEntry; |
1179 | |
|
1180 | 0 | for( const auto& rChangeAction : *pActionMap ) |
1181 | 0 | { |
1182 | |
|
1183 | 0 | if( pScChangeAction != rChangeAction.second ) |
1184 | 0 | xEntry = AppendChangeAction(rChangeAction.second, false, &rParent, false, true); |
1185 | 0 | else |
1186 | 0 | xEntry = AppendChangeAction(rChangeAction.second, false, &rParent, true, true); |
1187 | |
|
1188 | 0 | if (xEntry) |
1189 | 0 | { |
1190 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1191 | 0 | ScRedlineData* pEntryData = weld::fromId<ScRedlineData*>(rTreeView.get_id(*xEntry)); |
1192 | 0 | pEntryData->bIsRejectable=false; |
1193 | 0 | pEntryData->bIsAcceptable=false; |
1194 | 0 | pEntryData->bDisabled=true; |
1195 | |
|
1196 | 0 | bTheTestFlag=false; |
1197 | |
|
1198 | 0 | if (rChangeAction.second->IsDialogParent()) |
1199 | 0 | Expand(pChanges, rChangeAction.second, *xEntry); |
1200 | 0 | } |
1201 | 0 | } |
1202 | 0 | return bTheTestFlag; |
1203 | 0 | } |
1204 | | |
1205 | | bool ScAcceptChgDlg::Expand(const ScChangeTrack* pChanges, const ScChangeAction* pScChangeAction, |
1206 | | const weld::TreeIter& rEntry, bool bFilter) |
1207 | 0 | { |
1208 | 0 | bool bTheTestFlag = true; |
1209 | |
|
1210 | 0 | if (pChanges && pScChangeAction) |
1211 | 0 | { |
1212 | 0 | ScChangeActionMap aActionMap; |
1213 | |
|
1214 | 0 | GetDependents(pScChangeAction, aActionMap, rEntry); |
1215 | |
|
1216 | 0 | switch(pScChangeAction->GetType()) |
1217 | 0 | { |
1218 | 0 | case SC_CAT_CONTENT: |
1219 | 0 | { |
1220 | 0 | InsertContentChildren(&aActionMap, rEntry); |
1221 | 0 | bTheTestFlag=!bHasFilterEntry; |
1222 | 0 | break; |
1223 | 0 | } |
1224 | 0 | case SC_CAT_DELETE_COLS: |
1225 | 0 | case SC_CAT_DELETE_ROWS: |
1226 | 0 | case SC_CAT_DELETE_TABS: |
1227 | 0 | { |
1228 | 0 | InsertDeletedChildren(pScChangeAction, &aActionMap, rEntry); |
1229 | 0 | bTheTestFlag=!bHasFilterEntry; |
1230 | 0 | break; |
1231 | 0 | } |
1232 | 0 | default: |
1233 | 0 | { |
1234 | 0 | if(!bFilter) |
1235 | 0 | bTheTestFlag = InsertChildren(&aActionMap, rEntry); |
1236 | 0 | break; |
1237 | 0 | } |
1238 | 0 | } |
1239 | 0 | aActionMap.clear(); |
1240 | 0 | } |
1241 | 0 | return bTheTestFlag; |
1242 | 0 | } |
1243 | | |
1244 | | IMPL_LINK(ScAcceptChgDlg, ExpandingHandle, const weld::TreeIter&, rEntry, bool) |
1245 | 0 | { |
1246 | 0 | ScChangeTrack* pChanges=pDoc->GetChangeTrack(); |
1247 | 0 | if (pChanges) |
1248 | 0 | { |
1249 | 0 | m_xDialog->set_busy_cursor(true); |
1250 | 0 | ScChangeActionMap aActionMap; |
1251 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1252 | 0 | ScRedlineData* pEntryData = weld::fromId<ScRedlineData*>(rTreeView.get_id(rEntry)); |
1253 | 0 | if (!rTreeView.iter_has_child(rEntry)) |
1254 | 0 | { |
1255 | 0 | bool bTheTestFlag = true; |
1256 | |
|
1257 | 0 | if (pEntryData) |
1258 | 0 | { |
1259 | 0 | ScChangeAction* pScChangeAction=static_cast<ScChangeAction*>(pEntryData->pData); |
1260 | |
|
1261 | 0 | GetDependents(pScChangeAction, aActionMap, rEntry); |
1262 | |
|
1263 | 0 | switch (pScChangeAction->GetType()) |
1264 | 0 | { |
1265 | 0 | case SC_CAT_CONTENT: |
1266 | 0 | { |
1267 | 0 | bTheTestFlag = InsertContentChildren( &aActionMap, rEntry ); |
1268 | 0 | break; |
1269 | 0 | } |
1270 | 0 | case SC_CAT_DELETE_COLS: |
1271 | 0 | case SC_CAT_DELETE_ROWS: |
1272 | 0 | case SC_CAT_DELETE_TABS: |
1273 | 0 | { |
1274 | 0 | bTheTestFlag = InsertDeletedChildren( pScChangeAction, &aActionMap, rEntry ); |
1275 | 0 | break; |
1276 | 0 | } |
1277 | 0 | default: |
1278 | 0 | { |
1279 | 0 | bTheTestFlag = InsertChildren( &aActionMap, rEntry ); |
1280 | 0 | break; |
1281 | 0 | } |
1282 | 0 | } |
1283 | 0 | aActionMap.clear(); |
1284 | |
|
1285 | 0 | } |
1286 | 0 | else |
1287 | 0 | { |
1288 | 0 | bTheTestFlag = InsertAcceptedORejected(rEntry); |
1289 | 0 | } |
1290 | 0 | if (bTheTestFlag) |
1291 | 0 | { |
1292 | 0 | std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator()); |
1293 | 0 | rTreeView.insert(&rEntry, -1, &aStrNoEntry, nullptr, nullptr, nullptr, false, xEntry.get()); |
1294 | 0 | rTreeView.set_font_color(*xEntry, COL_GRAY); |
1295 | 0 | } |
1296 | 0 | } |
1297 | 0 | m_xDialog->set_busy_cursor(false); |
1298 | 0 | } |
1299 | 0 | return true; |
1300 | 0 | } |
1301 | | |
1302 | | void ScAcceptChgDlg::AppendChanges(const ScChangeTrack* pChanges,sal_uLong nStartAction, |
1303 | | sal_uLong nEndAction) |
1304 | 0 | { |
1305 | 0 | if(pChanges==nullptr) |
1306 | 0 | return; |
1307 | | |
1308 | 0 | std::unique_ptr<weld::TreeIter> xParent; |
1309 | 0 | m_xDialog->set_busy_cursor(true); |
1310 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1311 | 0 | rTreeView.freeze(); |
1312 | |
|
1313 | 0 | bool bTheFlag = false; |
1314 | |
|
1315 | 0 | bool bFilterFlag = pTPFilter->IsDate() || pTPFilter->IsRange() || |
1316 | 0 | pTPFilter->IsAuthor() || pTPFilter->IsComment(); |
1317 | |
|
1318 | 0 | bUseColor = bFilterFlag; |
1319 | |
|
1320 | 0 | for(sal_uLong i=nStartAction;i<=nEndAction;i++) |
1321 | 0 | { |
1322 | 0 | const ScChangeAction* pScChangeAction=pChanges->GetAction(i); |
1323 | 0 | if(pScChangeAction==nullptr) continue; |
1324 | | |
1325 | 0 | switch (pScChangeAction->GetState()) |
1326 | 0 | { |
1327 | 0 | case SC_CAS_VIRGIN: |
1328 | |
|
1329 | 0 | if (pScChangeAction->IsDialogRoot()) |
1330 | 0 | { |
1331 | 0 | bool bOnDemandChildren = !bFilterFlag && pScChangeAction->IsDialogParent(); |
1332 | 0 | if (pScChangeAction->IsDialogParent()) |
1333 | 0 | xParent = AppendChangeAction(pScChangeAction, bOnDemandChildren); |
1334 | 0 | else |
1335 | 0 | xParent = AppendFilteredAction(pScChangeAction, SC_CAS_VIRGIN, bOnDemandChildren); |
1336 | 0 | } |
1337 | 0 | else |
1338 | 0 | xParent.reset(); |
1339 | |
|
1340 | 0 | bTheFlag=true; |
1341 | 0 | break; |
1342 | | |
1343 | 0 | case SC_CAS_ACCEPTED: |
1344 | 0 | xParent.reset(); |
1345 | 0 | nAcceptCount++; |
1346 | 0 | break; |
1347 | | |
1348 | 0 | case SC_CAS_REJECTED: |
1349 | 0 | xParent.reset(); |
1350 | 0 | nRejectCount++; |
1351 | 0 | break; |
1352 | 0 | } |
1353 | | |
1354 | 0 | if (xParent && pScChangeAction->IsDialogParent() && bFilterFlag) |
1355 | 0 | { |
1356 | 0 | bool bTestFlag = bHasFilterEntry; |
1357 | 0 | bHasFilterEntry = false; |
1358 | 0 | if (Expand(pChanges,pScChangeAction,*xParent,!bTestFlag)&&!bTestFlag) |
1359 | 0 | rTreeView.remove(*xParent); |
1360 | 0 | } |
1361 | 0 | } |
1362 | | |
1363 | 0 | if( bTheFlag && (!pDoc->IsDocEditable() || pChanges->IsProtected()) ) |
1364 | 0 | bTheFlag=false; |
1365 | |
|
1366 | 0 | m_rTPView.EnableAccept(bTheFlag); |
1367 | 0 | m_rTPView.EnableAcceptAll(bTheFlag); |
1368 | 0 | m_rTPView.EnableReject(bTheFlag); |
1369 | 0 | m_rTPView.EnableRejectAll(bTheFlag); |
1370 | |
|
1371 | 0 | rTreeView.thaw(); |
1372 | 0 | m_xDialog->set_busy_cursor(false); |
1373 | 0 | } |
1374 | | |
1375 | | void ScAcceptChgDlg::RemoveEntries(sal_uLong nStartAction,sal_uLong nEndAction) |
1376 | 0 | { |
1377 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1378 | |
|
1379 | 0 | ScRedlineData* pEntryData = nullptr; |
1380 | 0 | if (std::unique_ptr<weld::TreeIter> xEntry = rTreeView.get_cursor()) |
1381 | 0 | pEntryData = weld::fromId<ScRedlineData*>(rTreeView.get_id(*xEntry)); |
1382 | |
|
1383 | 0 | std::unique_ptr<weld::TreeIter> xEntry = rTreeView.make_iterator(); |
1384 | 0 | if (!rTreeView.get_iter_first(*xEntry)) |
1385 | 0 | return; |
1386 | | |
1387 | 0 | sal_uLong nAction=0; |
1388 | 0 | if (pEntryData) |
1389 | 0 | nAction=pEntryData->nActionNo; |
1390 | |
|
1391 | 0 | if (nAction>=nStartAction && nAction<=nEndAction) |
1392 | 0 | rTreeView.set_cursor(*xEntry); |
1393 | |
|
1394 | 0 | std::vector<OUString> aIdsToRemove; |
1395 | |
|
1396 | 0 | do |
1397 | 0 | { |
1398 | 0 | OUString sId(rTreeView.get_id(*xEntry)); |
1399 | 0 | pEntryData = weld::fromId<ScRedlineData*>(sId); |
1400 | 0 | if (pEntryData) |
1401 | 0 | { |
1402 | 0 | nAction = pEntryData->nActionNo; |
1403 | 0 | if (nStartAction <= nAction && nAction <= nEndAction) |
1404 | 0 | { |
1405 | 0 | aIdsToRemove.push_back(sId); |
1406 | 0 | delete pEntryData; |
1407 | 0 | } |
1408 | 0 | } |
1409 | 0 | } |
1410 | 0 | while (rTreeView.iter_next(*xEntry)); |
1411 | |
|
1412 | 0 | rTreeView.freeze(); |
1413 | | |
1414 | | // MUST do it backwards, don't delete parents before children and GPF |
1415 | 0 | for (auto it = aIdsToRemove.rbegin(); it != aIdsToRemove.rend(); ++it) |
1416 | 0 | rTreeView.remove_id(*it); |
1417 | |
|
1418 | 0 | rTreeView.thaw(); |
1419 | 0 | } |
1420 | | |
1421 | | void ScAcceptChgDlg::UpdateEntries(const ScChangeTrack* pChgTrack, sal_uLong nStartAction,sal_uLong nEndAction) |
1422 | 0 | { |
1423 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1424 | 0 | rTreeView.freeze(); |
1425 | |
|
1426 | 0 | std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator()); |
1427 | 0 | std::unique_ptr<weld::TreeIter> xLastEntry(rTreeView.make_iterator()); |
1428 | 0 | std::unique_ptr<weld::TreeIter> xNextEntry(rTreeView.make_iterator()); |
1429 | |
|
1430 | 0 | bool bEntry = rTreeView.get_iter_first(*xEntry); |
1431 | 0 | bool bLastEntry = false; |
1432 | |
|
1433 | 0 | while (bEntry) |
1434 | 0 | { |
1435 | 0 | bool bRemove = false; |
1436 | 0 | ScRedlineData* pEntryData = weld::fromId<ScRedlineData*>(rTreeView.get_id(*xEntry)); |
1437 | 0 | if (pEntryData) |
1438 | 0 | { |
1439 | 0 | ScChangeAction* pScChangeAction= |
1440 | 0 | static_cast<ScChangeAction*>(pEntryData->pData); |
1441 | |
|
1442 | 0 | sal_uLong nAction=pScChangeAction->GetActionNumber(); |
1443 | |
|
1444 | 0 | if(nStartAction<=nAction && nAction<=nEndAction) bRemove=true; |
1445 | 0 | } |
1446 | |
|
1447 | 0 | bool bNextEntry; |
1448 | 0 | if (bRemove) |
1449 | 0 | { |
1450 | 0 | rTreeView.remove(*xEntry); |
1451 | 0 | delete pEntryData; |
1452 | |
|
1453 | 0 | if (!bLastEntry) |
1454 | 0 | bLastEntry = rTreeView.get_iter_first(*xLastEntry); |
1455 | 0 | if (bLastEntry) |
1456 | 0 | { |
1457 | 0 | rTreeView.copy_iterator(*xLastEntry, *xNextEntry); |
1458 | 0 | bNextEntry = rTreeView.iter_next(*xNextEntry); |
1459 | 0 | if (!bNextEntry) |
1460 | 0 | { |
1461 | 0 | rTreeView.copy_iterator(*xLastEntry, *xNextEntry); |
1462 | 0 | bLastEntry = false; |
1463 | 0 | } |
1464 | 0 | } |
1465 | 0 | else |
1466 | 0 | bNextEntry = false; |
1467 | 0 | } |
1468 | 0 | else |
1469 | 0 | { |
1470 | 0 | rTreeView.copy_iterator(*xEntry, *xLastEntry); |
1471 | 0 | bLastEntry = true; |
1472 | |
|
1473 | 0 | rTreeView.copy_iterator(*xEntry, *xNextEntry); |
1474 | 0 | bNextEntry = rTreeView.iter_next(*xNextEntry); |
1475 | 0 | } |
1476 | |
|
1477 | 0 | rTreeView.copy_iterator(*xNextEntry, *xEntry); |
1478 | 0 | bEntry = bNextEntry; |
1479 | 0 | } |
1480 | |
|
1481 | 0 | AppendChanges(pChgTrack,nStartAction,nEndAction); |
1482 | |
|
1483 | 0 | rTreeView.thaw(); |
1484 | 0 | } |
1485 | | |
1486 | | IMPL_LINK( ScAcceptChgDlg, ChgTrackModHdl, ScChangeTrack&, rChgTrack, void) |
1487 | 0 | { |
1488 | 0 | ScChangeTrackMsgQueue& aMsgQueue= rChgTrack.GetMsgQueue(); |
1489 | |
|
1490 | 0 | sal_uLong nStartAction; |
1491 | 0 | sal_uLong nEndAction; |
1492 | |
|
1493 | 0 | for (const auto& rMsg : aMsgQueue) |
1494 | 0 | { |
1495 | 0 | nStartAction = rMsg.nStartAction; |
1496 | 0 | nEndAction = rMsg.nEndAction; |
1497 | |
|
1498 | 0 | if(!bIgnoreMsg) |
1499 | 0 | { |
1500 | 0 | bNoSelection=true; |
1501 | |
|
1502 | 0 | switch(rMsg.eMsgType) |
1503 | 0 | { |
1504 | 0 | case ScChangeTrackMsgType::Append: |
1505 | 0 | AppendChanges(&rChgTrack,nStartAction,nEndAction); |
1506 | 0 | break; |
1507 | 0 | case ScChangeTrackMsgType::Remove: |
1508 | 0 | RemoveEntries(nStartAction,nEndAction); |
1509 | 0 | break; |
1510 | 0 | case ScChangeTrackMsgType::Parent: |
1511 | 0 | case ScChangeTrackMsgType::Change: //bNeedsUpdate=true; |
1512 | 0 | UpdateEntries(&rChgTrack,nStartAction,nEndAction); |
1513 | 0 | break; |
1514 | 0 | default: assert(false); break; |
1515 | 0 | } |
1516 | 0 | } |
1517 | 0 | } |
1518 | | |
1519 | 0 | aMsgQueue.clear(); |
1520 | 0 | } |
1521 | | |
1522 | | IMPL_LINK_NOARG(ScAcceptChgDlg, ReOpenTimerHdl, Timer *, void) |
1523 | 0 | { |
1524 | 0 | ScSimpleRefDlgWrapper::SetAutoReOpen(true); |
1525 | 0 | m_xAcceptChgCtr->ShowFilterPage(); |
1526 | 0 | RefHandle(nullptr); |
1527 | 0 | } |
1528 | | |
1529 | | IMPL_LINK_NOARG(ScAcceptChgDlg, UpdateSelectionHdl, Timer *, void) |
1530 | 0 | { |
1531 | 0 | ScTabView* pTabView = pViewData->GetView(); |
1532 | |
|
1533 | 0 | bool bAcceptFlag = true; |
1534 | 0 | bool bRejectFlag = true; |
1535 | |
|
1536 | 0 | pTabView->DoneBlockMode(); // clears old marking |
1537 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1538 | 0 | std::vector<const ScChangeAction*> aActions; |
1539 | 0 | rTreeView.selected_foreach([&rTreeView, &bAcceptFlag, &bRejectFlag, &aActions](weld::TreeIter& rEntry){ |
1540 | 0 | ScRedlineData* pEntryData = weld::fromId<ScRedlineData*>(rTreeView.get_id(rEntry)); |
1541 | 0 | if (pEntryData) |
1542 | 0 | { |
1543 | 0 | bRejectFlag &= pEntryData->bIsRejectable; |
1544 | 0 | bAcceptFlag &= pEntryData->bIsAcceptable; |
1545 | |
|
1546 | 0 | const ScChangeAction* pScChangeAction = static_cast<ScChangeAction*>(pEntryData->pData); |
1547 | 0 | if( pScChangeAction && (pScChangeAction->GetType() != SC_CAT_DELETE_TABS) && |
1548 | 0 | (!pEntryData->bDisabled || pScChangeAction->IsVisible()) ) |
1549 | 0 | { |
1550 | 0 | aActions.push_back(pScChangeAction); |
1551 | 0 | } |
1552 | 0 | } |
1553 | 0 | else |
1554 | 0 | { |
1555 | 0 | bAcceptFlag = false; |
1556 | 0 | bRejectFlag = false; |
1557 | 0 | } |
1558 | 0 | return false; |
1559 | 0 | }); |
1560 | |
|
1561 | 0 | bool bContMark = false; |
1562 | 0 | for (size_t i = 0, nCount = aActions.size(); i < nCount; ++i) |
1563 | 0 | { |
1564 | 0 | const ScBigRange& rBigRange = aActions[i]->GetBigRange(); |
1565 | 0 | if (rBigRange.IsValid(*pDoc) && m_xDialog->has_toplevel_focus()) |
1566 | 0 | { |
1567 | 0 | bool bSetCursor = i == nCount - 1; |
1568 | 0 | pTabView->MarkRange(rBigRange.MakeRange(*pDoc), bSetCursor, bContMark); |
1569 | 0 | bContMark = true; |
1570 | 0 | } |
1571 | 0 | } |
1572 | |
|
1573 | 0 | ScChangeTrack* pChanges = pDoc->GetChangeTrack(); |
1574 | 0 | bool bEnable = pDoc->IsDocEditable() && pChanges && !pChanges->IsProtected(); |
1575 | 0 | m_rTPView.EnableAccept(bAcceptFlag && bEnable); |
1576 | 0 | m_rTPView.EnableReject(bRejectFlag && bEnable); |
1577 | 0 | } |
1578 | | |
1579 | | IMPL_LINK(ScAcceptChgDlg, CommandHdl, const CommandEvent&, rCEvt, bool) |
1580 | 0 | { |
1581 | 0 | if (rCEvt.GetCommand() != CommandEventId::ContextMenu) |
1582 | 0 | return false; |
1583 | | |
1584 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1585 | 0 | std::unique_ptr<weld::TreeIter> xEntry = rTreeView.get_cursor(); |
1586 | 0 | if (xEntry) |
1587 | 0 | rTreeView.select(*xEntry); |
1588 | |
|
1589 | 0 | int nSortedCol = rTreeView.get_sort_column(); |
1590 | 0 | for (sal_Int32 i = 0; i < 5; ++i) |
1591 | 0 | m_xSortMenu->set_active("calcsort" + OUString::number(i), i == nSortedCol); |
1592 | |
|
1593 | 0 | m_xPopup->set_sensitive(u"calcedit"_ustr, false); |
1594 | |
|
1595 | 0 | if (pDoc->IsDocEditable() && xEntry) |
1596 | 0 | { |
1597 | 0 | ScRedlineData* pEntryData = weld::fromId<ScRedlineData*>(rTreeView.get_id(*xEntry)); |
1598 | 0 | if (pEntryData) |
1599 | 0 | { |
1600 | 0 | ScChangeAction* pScChangeAction = static_cast<ScChangeAction*>(pEntryData->pData); |
1601 | 0 | if (pScChangeAction && !rTreeView.get_iter_depth(*xEntry)) |
1602 | 0 | m_xPopup->set_sensitive(u"calcedit"_ustr, true); |
1603 | 0 | } |
1604 | 0 | } |
1605 | |
|
1606 | 0 | OUString sCommand = m_xPopup->popup_at_rect(&rTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1))); |
1607 | |
|
1608 | 0 | if (!sCommand.isEmpty()) |
1609 | 0 | { |
1610 | 0 | if (sCommand == "calcedit") |
1611 | 0 | { |
1612 | 0 | if (xEntry) |
1613 | 0 | { |
1614 | 0 | ScRedlineData* pEntryData = weld::fromId<ScRedlineData*>(rTreeView.get_id(*xEntry)); |
1615 | 0 | if (pEntryData) |
1616 | 0 | { |
1617 | 0 | ScChangeAction* pScChangeAction = static_cast<ScChangeAction*>(pEntryData->pData); |
1618 | 0 | pViewData->GetDocShell()->ExecuteChangeCommentDialog(pScChangeAction, m_xDialog.get(), false); |
1619 | 0 | } |
1620 | 0 | } |
1621 | 0 | } |
1622 | 0 | else |
1623 | 0 | { |
1624 | 0 | int nDialogCol = o3tl::toInt32(sCommand.subView(8)); |
1625 | 0 | pTheView->HeaderBarClick(nDialogCol); |
1626 | 0 | } |
1627 | 0 | } |
1628 | |
|
1629 | 0 | return true; |
1630 | 0 | } |
1631 | | |
1632 | | namespace |
1633 | | { |
1634 | | //at one point we were writing multiple AcceptChgDat strings, |
1635 | | //so strip all of them and keep the results of the last one |
1636 | | OUString lcl_StripAcceptChgDat(OUString &rExtraString) |
1637 | 0 | { |
1638 | 0 | OUString aStr; |
1639 | 0 | while (true) |
1640 | 0 | { |
1641 | 0 | sal_Int32 nPos = rExtraString.indexOf("AcceptChgDat:"); |
1642 | 0 | if (nPos == -1) |
1643 | 0 | break; |
1644 | | // Try to read the alignment string "ALIGN:(...)"; if it is missing |
1645 | | // we have an old version |
1646 | 0 | sal_Int32 n1 = rExtraString.indexOf('(', nPos); |
1647 | 0 | if ( n1 != -1 ) |
1648 | 0 | { |
1649 | 0 | sal_Int32 n2 = rExtraString.indexOf(')', n1); |
1650 | 0 | if ( n2 != -1 ) |
1651 | 0 | { |
1652 | | // cut out alignment string |
1653 | 0 | aStr = rExtraString.copy(nPos, n2 - nPos + 1); |
1654 | 0 | rExtraString = rExtraString.replaceAt(nPos, n2 - nPos + 1, u""); |
1655 | 0 | aStr = aStr.copy( n1-nPos+1 ); |
1656 | 0 | } |
1657 | 0 | } |
1658 | 0 | } |
1659 | 0 | return aStr; |
1660 | 0 | } |
1661 | | } |
1662 | | |
1663 | | void ScAcceptChgDlg::Initialize(SfxChildWinInfo* pInfo) |
1664 | 0 | { |
1665 | 0 | OUString aStr; |
1666 | 0 | if (pInfo && !pInfo->aExtraString.isEmpty()) |
1667 | 0 | aStr = lcl_StripAcceptChgDat(pInfo->aExtraString); |
1668 | |
|
1669 | 0 | SfxModelessDialogController::Initialize(pInfo); |
1670 | |
|
1671 | 0 | if (aStr.isEmpty()) |
1672 | 0 | return; |
1673 | | |
1674 | 0 | int nCount = aStr.toInt32(); |
1675 | 0 | if (nCount <= 2) |
1676 | 0 | return; |
1677 | | |
1678 | 0 | std::vector<int> aEndPos; |
1679 | |
|
1680 | 0 | for (int i = 0; i < nCount; ++i) |
1681 | 0 | { |
1682 | 0 | sal_Int32 n1 = aStr.indexOf(';'); |
1683 | 0 | aStr = aStr.copy( n1+1 ); |
1684 | 0 | aEndPos.push_back(aStr.toInt32()); |
1685 | 0 | } |
1686 | |
|
1687 | 0 | std::vector<int> aWidths; |
1688 | 0 | for (int i = 1; i < nCount; ++i) |
1689 | 0 | aWidths.push_back(aEndPos[i] - aEndPos[i - 1]); |
1690 | | |
1691 | | // turn column end points back to column widths, ignoring the small |
1692 | | // value used for the expander column |
1693 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1694 | 0 | rTreeView.set_column_fixed_widths(aWidths); |
1695 | 0 | } |
1696 | | |
1697 | | void ScAcceptChgDlg::FillInfo(SfxChildWinInfo& rInfo) const |
1698 | 0 | { |
1699 | 0 | SfxModelessDialogController::FillInfo(rInfo); |
1700 | | //remove any old one before adding a new one |
1701 | 0 | lcl_StripAcceptChgDat(rInfo.aExtraString); |
1702 | 0 | rInfo.aExtraString += "AcceptChgDat:("; |
1703 | |
|
1704 | 0 | const int nTabCount = 5; |
1705 | |
|
1706 | 0 | rInfo.aExtraString += OUString::number(nTabCount); |
1707 | 0 | rInfo.aExtraString += ";"; |
1708 | |
|
1709 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1710 | 0 | std::vector<int> aWidths; |
1711 | | // turn column widths back into column end points for compatibility |
1712 | | // with how they used to be stored, including a small value for the |
1713 | | // expander column |
1714 | 0 | aWidths.push_back(rTreeView.get_checkbox_column_width()); |
1715 | 0 | for (int i = 0; i < nTabCount - 1; ++i) |
1716 | 0 | aWidths.push_back(aWidths.back() + rTreeView.get_column_width(i)); |
1717 | |
|
1718 | 0 | for (auto a : aWidths) |
1719 | 0 | { |
1720 | 0 | rInfo.aExtraString += OUString::number(a); |
1721 | 0 | rInfo.aExtraString += ";"; |
1722 | 0 | } |
1723 | 0 | rInfo.aExtraString += ")"; |
1724 | 0 | } |
1725 | | |
1726 | 0 | #define CALC_DATE 3 |
1727 | 0 | #define CALC_POS 1 |
1728 | | |
1729 | | int ScAcceptChgDlg::ColCompareHdl(const weld::TreeIter& rLeft, const weld::TreeIter& rRight) const |
1730 | 0 | { |
1731 | 0 | weld::TreeView& rTreeView = pTheView->GetWidget(); |
1732 | |
|
1733 | 0 | sal_Int32 nCompare = 0; |
1734 | 0 | SCCOL nSortCol = rTreeView.get_sort_column(); |
1735 | |
|
1736 | 0 | if (CALC_DATE == nSortCol) |
1737 | 0 | { |
1738 | 0 | RedlineData* pLeftData = weld::fromId<RedlineData*>(rTreeView.get_id(rLeft)); |
1739 | 0 | RedlineData* pRightData = weld::fromId<RedlineData*>(rTreeView.get_id(rRight)); |
1740 | 0 | if (pLeftData && pRightData) |
1741 | 0 | { |
1742 | 0 | if(pLeftData->aDateTime < pRightData->aDateTime) |
1743 | 0 | nCompare = -1; |
1744 | 0 | else if(pLeftData->aDateTime > pRightData->aDateTime) |
1745 | 0 | nCompare = 1; |
1746 | 0 | return nCompare; |
1747 | 0 | } |
1748 | 0 | } |
1749 | 0 | else if (CALC_POS == nSortCol) |
1750 | 0 | { |
1751 | 0 | ScRedlineData* pLeftData = weld::fromId<ScRedlineData*>(rTreeView.get_id(rLeft)); |
1752 | 0 | ScRedlineData* pRightData = weld::fromId<ScRedlineData*>(rTreeView.get_id(rRight)); |
1753 | 0 | if (pLeftData && pRightData) |
1754 | 0 | { |
1755 | 0 | nCompare = 1; |
1756 | |
|
1757 | 0 | if(pLeftData->nTable < pRightData->nTable) |
1758 | 0 | nCompare = -1; |
1759 | 0 | else if(pLeftData->nTable == pRightData->nTable) |
1760 | 0 | { |
1761 | 0 | if(pLeftData->nRow < pRightData->nRow) |
1762 | 0 | nCompare = -1; |
1763 | 0 | else if(pLeftData->nRow == pRightData->nRow) |
1764 | 0 | { |
1765 | 0 | if(pLeftData->nCol < pRightData->nCol) |
1766 | 0 | nCompare = -1; |
1767 | 0 | else if(pLeftData->nCol == pRightData->nCol) |
1768 | 0 | nCompare = 0; |
1769 | 0 | } |
1770 | 0 | } |
1771 | |
|
1772 | 0 | return nCompare; |
1773 | 0 | } |
1774 | 0 | } |
1775 | | |
1776 | 0 | return ScGlobal::GetCaseCollator().compareString(rTreeView.get_text(rLeft, nSortCol), |
1777 | 0 | rTreeView.get_text(rRight, nSortCol)); |
1778 | 0 | } |
1779 | | |
1780 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |