Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: */