Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/sc/source/ui/miscdlgs/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 57 kB image not shown  

Quelle  acredlin.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <svl/undo.hxx>
#include <unotools/textsearch.hxx>
#include <unotools/localedatawrapper.hxx>
#include <unotools/collatorwrapper.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/basedlgs.hxx>
#include <vcl/commandevent.hxx>
#include <o3tl/string_view.hxx>

#include <acredlin.hxx>
#include <global.hxx>
#include <reffact.hxx>
#include <document.hxx>
#include <docsh.hxx>
#include <scresid.hxx>
#include <strings.hrc>
#include <scmod.hxx>
#include <tabvwsh.hxx>

// defines -------------------------------------------------------------------

#define RD_SPECIAL_NONE         0
#define RD_SPECIAL_CONTENT      1
#define RD_SPECIAL_VISCONTENT   2


ScRedlinData::ScRedlinData()
{
    nInfo=RD_SPECIAL_NONE;
    nActionNo=0;
    pData=nullptr;
    bDisabled=false;
    bIsRejectable=false;
    bIsAcceptable=false;
    nTable=SCTAB_MAX;
    nCol=SCCOL_MAX;
    nRow=SCROW_MAX;
}

ScRedlinData::~ScRedlinData()
{
    nInfo=RD_SPECIAL_NONE;
    nActionNo=0;
    pData=nullptr;
    bDisabled=false;
    bIsRejectable=false;
    bIsAcceptable=false;
}


ScAcceptChgDlg::ScAcceptChgDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
    ScViewData& rViewData)
    : SfxModelessDialogController(pB, pCW, pParent,
        u"svx/ui/acceptrejectchangesdialog.ui"_ustr, u"AcceptRejectChangesDialog"_ustr)
    , aSelectionIdle( "ScAcceptChgDlg aSelectionIdle" )
    , aReOpenIdle("ScAcceptChgDlg ReOpenIdle")
    , pViewData( &rViewData )
    , pDoc( &rViewData.GetDocument() )
    , aStrInsertCols(ScResId(STR_CHG_INSERT_COLS))
    , aStrInsertRows(ScResId(STR_CHG_INSERT_ROWS))
    , aStrInsertTabs(ScResId(STR_CHG_INSERT_TABS))
    , aStrDeleteCols(ScResId(STR_CHG_DELETE_COLS))
    , aStrDeleteRows(ScResId(STR_CHG_DELETE_ROWS))
    , aStrDeleteTabs(ScResId(STR_CHG_DELETE_TABS))
    , aStrMove(ScResId(STR_CHG_MOVE))
    , aStrContent(ScResId(STR_CHG_CONTENT))
    , aStrReject(ScResId(STR_CHG_REJECT))
    , aStrAllAccepted(ScResId(STR_CHG_ACCEPTED))
    , aStrAllRejected(ScResId(STR_CHG_REJECTED))
    , aStrNoEntry(ScResId(STR_CHG_NO_ENTRY))
    , aStrContentWithChild(ScResId(STR_CHG_CONTENT_WITH_CHILD))
    , aStrChildContent(ScResId(STR_CHG_CHILD_CONTENT))
    , aStrChildOrgContent(ScResId(STR_CHG_CHILD_ORGCONTENT))
    , aStrEmpty(ScResId(STR_CHG_EMPTY))
    , aUnknown(u"Unknown"_ustr)
    , bIgnoreMsg(false)
    , bNoSelection(false)
    , bHasFilterEntry(false)
    , bUseColor(false)
    , m_xContentArea(m_xDialog->weld_content_area())
    , m_xPopup(m_xBuilder->weld_menu(u"calcmenu"_ustr))
    , m_xSortMenu(m_xBuilder->weld_menu(u"calcsortmenu"_ustr))
{
    m_xAcceptChgCtr.reset(new SvxAcceptChgCtr(m_xContentArea.get()));
    nAcceptCount=0;
    nRejectCount=0;
    aReOpenIdle.SetInvokeHandler(LINK( this, ScAcceptChgDlg, ReOpenTimerHdl ));

    pTPFilter = m_xAcceptChgCtr->GetFilterPage();
    pTPView = m_xAcceptChgCtr->GetViewPage();

    // tdf#136062 Don't use "Reject/Clear formatting" instead of "Reject" buttons in Calc
    pTPView->EnableClearFormat(false);
    pTPView->EnableClearFormatAll(false);

    pTheView = pTPView->GetTableControl();
    pTheView->SetCalcView();
    aSelectionIdle.SetInvokeHandler(LINK( this, ScAcceptChgDlg, UpdateSelectionHdl ));

    pTPFilter->SetReadyHdl(LINK( this, ScAcceptChgDlg, FilterHandle ));
    pTPFilter->SetRefHdl(LINK( this, ScAcceptChgDlg, RefHandle ));
    pTPFilter->HideRange(false);
    pTPView->SetRejectClickHdl( LINK( this, ScAcceptChgDlg,RejectHandle));
    pTPView->SetAcceptClickHdl( LINK(this, ScAcceptChgDlg, AcceptHandle));
    pTPView->SetRejectAllClickHdl( LINK( this, ScAcceptChgDlg,RejectAllHandle));
    pTPView->SetAcceptAllClickHdl( LINK(this, ScAcceptChgDlg, AcceptAllHandle));

    weld::TreeView& rTreeView = pTheView->GetWidget();
    rTreeView.connect_expanding(LINK(this, ScAcceptChgDlg, ExpandingHandle));
    rTreeView.connect_selection_changed(LINK(this, ScAcceptChgDlg, SelectHandle));
    rTreeView.connect_popup_menu(LINK(this, ScAcceptChgDlg, CommandHdl));
    rTreeView.set_sort_func([this](const weld::TreeIter& rLeft, const weld::TreeIter&&nbsp;rRight){
        return ColCompareHdl(rLeft, rRight);
    });
    rTreeView.set_selection_mode(SelectionMode::Multiple);

    Init();

    UpdateView();

    std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
    if (rTreeView.get_iter_first(*xEntry))
        rTreeView.select(*xEntry);
}

ScAcceptChgDlg::~ScAcceptChgDlg()
{
    ClearView();
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();

    if (pChanges)
    {
        Link<ScChangeTrack&,void> aLink;
        pChanges->SetModifiedLink(aLink);
    }
}

void ScAcceptChgDlg::ReInit(ScViewData& rViewData)
{
    pViewData = &rViewData;
    pDoc = &rViewData.GetDocument();

    bNoSelection=false;
    bIgnoreMsg=false;
    nAcceptCount=0;
    nRejectCount=0;

    //  don't call Init here (switching between views), just set link below
    //  (dialog is just hidden, not deleted anymore, when switching views)
    ClearView();
    UpdateView();

    ScChangeTrack* pChanges = pDoc->GetChangeTrack();
    if ( pChanges )
        pChanges->SetModifiedLink( LINK( this, ScAcceptChgDlg, ChgTrackModHdl ) );
}

void ScAcceptChgDlg::Init()
{
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();

    if(pChanges!=nullptr)
    {
        pChanges->SetModifiedLink( LINK( this, ScAcceptChgDlg,ChgTrackModHdl));
        aChangeViewSet.SetTheAuthorToShow(pChanges->GetUser());
        pTPFilter->ClearAuthors();
        const std::set<OUString>& rUserColl = pChanges->GetUserCollection();
        for (const auto& rItem : rUserColl)
            pTPFilter->InsertAuthor(rItem);
    }

    ScChangeViewSettings* pViewSettings=pDoc->GetChangeViewSettings();
    if ( pViewSettings!=nullptr )
        aChangeViewSet = *pViewSettings;
    // adjust TimeField for filter tabpage
    aChangeViewSet.AdjustDateMode( *pDoc );

    pTPFilter->CheckDate(aChangeViewSet.HasDate());

    DateTime aEmpty(DateTime::EMPTY);

    DateTime aDateTime(aChangeViewSet.GetTheFirstDateTime());
    if (aDateTime != aEmpty)
    {
        pTPFilter->SetFirstDate(aDateTime);
        pTPFilter->SetFirstTime(aDateTime);
    }
    aDateTime = aChangeViewSet.GetTheLastDateTime();
    if (aDateTime != aEmpty)
    {
        pTPFilter->SetLastDate(aDateTime);
        pTPFilter->SetLastTime(aDateTime);
    }

    pTPFilter->SetDateMode(static_cast<sal_uInt16>(aChangeViewSet.GetTheDateMode()));
    pTPFilter->CheckComment(aChangeViewSet.HasComment());
    pTPFilter->SetComment(aChangeViewSet.GetTheComment());

    pTPFilter->CheckAuthor(aChangeViewSet.HasAuthor());
    OUString aString=aChangeViewSet.GetTheAuthorToShow();
    if(!aString.isEmpty())
    {
        pTPFilter->SelectAuthor(aString);
        if(pTPFilter->GetSelectedAuthor()!=aString)
        {
            pTPFilter->InsertAuthor(aString);
            pTPFilter->SelectAuthor(aString);
        }
    }
    else
        pTPFilter->SelectedAuthorPos(0);

    pTPFilter->CheckRange(aChangeViewSet.HasRange());

    aRangeList=aChangeViewSet.GetTheRangeList();

    if( !aChangeViewSet.GetTheRangeList().empty() )
    {
        const ScRange & rRangeEntry = aChangeViewSet.GetTheRangeList().front();
        OUString aRefStr(rRangeEntry.Format(*pDoc, ScRefFlags::RANGE_ABS_3D));
        pTPFilter->SetRange(aRefStr);
    }

    // init filter
    if(!(pTPFilter->IsDate()||pTPFilter->IsRange()||
        pTPFilter->IsAuthor()||pTPFilter->IsComment()))
        return;

    pTheView->SetFilterDate(pTPFilter->IsDate());
    pTheView->SetDateTimeMode(pTPFilter->GetDateMode());
    pTheView->SetFirstDate(pTPFilter->GetFirstDate());
    pTheView->SetLastDate(pTPFilter->GetLastDate());
    pTheView->SetFirstTime(pTPFilter->GetFirstTime());
    pTheView->SetLastTime(pTPFilter->GetLastTime());
    pTheView->SetFilterAuthor(pTPFilter->IsAuthor());
    pTheView->SetAuthor(pTPFilter->GetSelectedAuthor());

    pTheView->SetFilterComment(pTPFilter->IsComment());

    utl::SearchParam aSearchParam( pTPFilter->GetComment(),
            utl::SearchParam::SearchType::Regexp,false );

    pTheView->SetCommentParams(&aSearchParam);

    pTheView->UpdateFilterTest();
}

void ScAcceptChgDlg::ClearView()
{
    nAcceptCount=0;
    nRejectCount=0;
    weld::TreeView& rTreeView = pTheView->GetWidget();
    rTreeView.all_foreach(
        [&rTreeView](weld::TreeIter& rEntry)
        {
            ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rEntry));
            delete pEntryData;
            return false;
        });
    rTreeView.freeze();
    rTreeView.clear();
    rTreeView.thaw();
}

OUString* ScAcceptChgDlg::MakeTypeString(ScChangeActionType eType)
{
    OUString* pStr;

    switch(eType)
    {

        case SC_CAT_INSERT_COLS:    pStr=&aStrInsertCols;break;
        case SC_CAT_INSERT_ROWS:    pStr=&aStrInsertRows;break;
        case SC_CAT_INSERT_TABS:    pStr=&aStrInsertTabs;break;
        case SC_CAT_DELETE_COLS:    pStr=&aStrDeleteCols;break;
        case SC_CAT_DELETE_ROWS:    pStr=&aStrDeleteRows;break;
        case SC_CAT_DELETE_TABS:    pStr=&aStrDeleteTabs;break;
        case SC_CAT_MOVE:           pStr=&aStrMove;break;
        case SC_CAT_CONTENT:        pStr=&aStrContent;break;
        case SC_CAT_REJECT:         pStr=&aStrReject;break;
        default:                    pStr=&aUnknown;break;
    }
    return pStr;
}

bool ScAcceptChgDlg::IsValidAction(const ScChangeAction* pScChangeAction)
{
    if(pScChangeAction==nullptr) return false;

    bool bFlag = false;

    ScRange aRef=pScChangeAction->GetBigRange().MakeRange(*pDoc);
    const OUString& aUser=pScChangeAction->GetUser();
    DateTime aDateTime=pScChangeAction->GetDateTime();

    ScChangeActionType eType=pScChangeAction->GetType();
    OUString aDesc;

    OUString aComment = pScChangeAction->GetComment().replaceAll("\n""");

    if(eType==SC_CAT_CONTENT)
    {
        if(!pScChangeAction->IsDialogParent())
            aDesc = pScChangeAction->GetDescription(*pDoc, true);
    }
    else
        aDesc = pScChangeAction->GetDescription(*pDoc, !pScChangeAction->IsMasterDelete());

    if (!aDesc.isEmpty())
    {
        aComment += " (" + aDesc + ")";
    }

    if (pTheView->IsValidEntry(aUser, aDateTime, aComment))
    {
        if(pTPFilter->IsRange())
        {
            for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i )
            {
                ScRange const & rRangeEntry = aRangeList[ i ];
                if (rRangeEntry.Intersects(aRef)) {
                    bFlag = true;
                    break;
                }
            }
        }
        else
            bFlag=true;
    }

    return bFlag;
}

std::unique_ptr<weld::TreeIter> ScAcceptChgDlg::AppendChangeAction(
    const ScChangeAction* pScChangeAction, bool bCreateOnDemand,
    const weld::TreeIter* pParent, bool bDelMaster, bool bDisabled)
{
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();

    if(pScChangeAction==nullptr || pChanges==nullptr) return nullptr;

    bool bFlag = false;

    ScRange aRef=pScChangeAction->GetBigRange().MakeRange(*pDoc);
    DateTime aDateTime=pScChangeAction->GetDateTime();

    ScChangeActionType eType=pScChangeAction->GetType();
    OUString aActionString;
    OUString aRefStr;
    OUString aUser;
    OUString aDate;
    OUString aDesc;

    std::unique_ptr<ScRedlinData> pNewData(new ScRedlinData);
    pNewData->pData=const_cast<ScChangeAction *>(pScChangeAction);
    pNewData->nActionNo=pScChangeAction->GetActionNumber();
    pNewData->bIsAcceptable=pScChangeAction->IsClickable();
    pNewData->bIsRejectable=pScChangeAction->IsRejectable();
    pNewData->bDisabled=!pNewData->bIsAcceptable || bDisabled;
    pNewData->aDateTime=aDateTime;
    pNewData->nRow  = aRef.aStart.Row();
    pNewData->nCol  = aRef.aStart.Col();
    pNewData->nTable= aRef.aStart.Tab();

    if(eType==SC_CAT_CONTENT)
    {
        if(pScChangeAction->IsDialogParent())
        {
            aActionString = aStrContentWithChild;
            pNewData->nInfo=RD_SPECIAL_VISCONTENT;
            pNewData->bIsRejectable=false;
            pNewData->bIsAcceptable=false;
        }
        else
        {
            aActionString = *MakeTypeString(eType);
            aDesc = pScChangeAction->GetDescription(*pDoc, true);
        }
    }
    else
    {
        aActionString = *MakeTypeString(eType);

        if(bDelMaster)
        {
            aDesc = pScChangeAction->GetDescription(*pDoc,true);
            pNewData->bDisabled=true;
            pNewData->bIsRejectable=false;
        }
        else
            aDesc = pScChangeAction->GetDescription(*pDoc, !pScChangeAction->IsMasterDelete());

    }

    aRefStr = pScChangeAction->GetRefString(*pDoc, true);

    bool bIsGenerated = false;

    if(!pChanges->IsGenerated(pScChangeAction->GetActionNumber()))
    {
        aUser = pScChangeAction->GetUser();
        aDate = ScGlobal::getLocaleData().getDate(aDateTime) + " " + ScGlobal::getLocaleData().getTime(aDateTime);
        bIsGenerated = false;
    }
    else
    {
        bIsGenerated = true;
    }

    OUString aComment = pScChangeAction->GetComment().replaceAll("\n""");

    if (!aDesc.isEmpty())
    {
        aComment +=  " (" + aDesc + ")";
    }

    if (pTheView->IsValidEntry(aUser, aDateTime) || bIsGenerated)
    {
        if (pTheView->IsValidComment(aComment))
        {
            if(pTPFilter->IsRange())
            {
                for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i )
                {
                    ScRange const & rRangeEntry = aRangeList[ i ];
                    if( rRangeEntry.Intersects(aRef) )
                    {
                        bHasFilterEntry=true;
                        bFlag=true;
                        break;
                    }
                }
            }
            else if(!bIsGenerated)
            {
                bHasFilterEntry=true;
                bFlag=true;
            }
        }
    }

    weld::TreeView& rTreeView = pTheView->GetWidget();
    std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
    OUString sId(weld::toId(pNewData.release()));
    rTreeView.insert(pParent, -1, &aActionString, &sId, nullptr, nullptr, bCreateOnDemand, xEntry.get());
    rTreeView.set_text( *xEntry, aRefStr, 1);
    if (!aUser.isEmpty())
        rTreeView.set_text( *xEntry, aUser, 2);
    if (!aDate.isEmpty())
        rTreeView.set_text( *xEntry, aDate, 3);
    if (!aComment.isEmpty())
        rTreeView.set_text( *xEntry, aComment, 4);
    if (!bFlag && bUseColor && !pParent)
    {
        rTreeView.set_font_color(*xEntry, COL_LIGHTBLUE);
    }
    else if (bFlag && bUseColor && pParent)
    {
        rTreeView.set_font_color(*xEntry, COL_GREEN);

        std::unique_ptr<weld::TreeIter> xExpEntry(rTreeView.make_iterator(pParent));

        while (!rTreeView.get_row_expanded(*xExpEntry))
        {
            if (rTreeView.get_iter_depth(*xExpEntry))
                rTreeView.expand_row(*xExpEntry);

            if (!rTreeView.iter_parent(*xExpEntry))
                break;
        }
    }
    return xEntry;
}

std::unique_ptr<weld::TreeIter> ScAcceptChgDlg::AppendFilteredAction(
    const ScChangeAction* pScChangeAction, ScChangeActionState eState,
    bool bCreateOnDemand,
    const weld::TreeIter* pParent, bool bDelMaster, bool bDisabled)
{
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();

    if(pScChangeAction==nullptr || pChanges==nullptr) return nullptr;

    bool bIsGenerated = pChanges->IsGenerated(pScChangeAction->GetActionNumber());

    bool bFlag = false;

    ScRange aRef=pScChangeAction->GetBigRange().MakeRange(*pDoc);
    const OUString& aUser=pScChangeAction->GetUser();
    DateTime aDateTime=pScChangeAction->GetDateTime();

    if (pTheView->IsValidEntry(aUser, aDateTime) || bIsGenerated)
    {
        if(pTPFilter->IsRange())
        {
            for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i )
            {
                ScRange const & rRangeEntry=aRangeList[ i ];
                if( rRangeEntry.Intersects(aRef) )
                {
                    if( pScChangeAction->GetState()==eState )
                        bFlag = true;
                    break;
                }
            }
        }
        else if(pScChangeAction->GetState()==eState && !bIsGenerated)
            bFlag = true;
    }

    std::unique_ptr<weld::TreeIter> xEntry;
    if(bFlag)
    {
        ScChangeActionType eType=pScChangeAction->GetType();
        OUString aActionString;
        OUString aDesc;

        std::unique_ptr<ScRedlinData> pNewData(new ScRedlinData);
        pNewData->pData=const_cast<ScChangeAction *>(pScChangeAction);
        pNewData->nActionNo=pScChangeAction->GetActionNumber();
        pNewData->bIsAcceptable=pScChangeAction->IsClickable();
        pNewData->bIsRejectable=pScChangeAction->IsRejectable();
        pNewData->bDisabled=!pNewData->bIsAcceptable || bDisabled;
        pNewData->aDateTime=aDateTime;
        pNewData->nRow  = aRef.aStart.Row();
        pNewData->nCol  = aRef.aStart.Col();
        pNewData->nTable= aRef.aStart.Tab();

        if(eType==SC_CAT_CONTENT)
        {
            if(pScChangeAction->IsDialogParent())
            {
                aActionString=aStrContentWithChild;
                pNewData->nInfo=RD_SPECIAL_VISCONTENT;
                pNewData->bIsRejectable=false;
                pNewData->bIsAcceptable=false;
            }
            else
            {
                aActionString=*MakeTypeString(eType);
                aDesc = pScChangeAction->GetDescription(*pDoc, true);
            }
        }
        else
        {
            aActionString=*MakeTypeString(eType);

            if(bDelMaster)
            {
                aDesc = pScChangeAction->GetDescription(*pDoc,true);
                pNewData->bDisabled=true;
                pNewData->bIsRejectable=false;
            }
            else
                aDesc = pScChangeAction->GetDescription(*pDoc,!pScChangeAction->IsMasterDelete());

        }


        OUString aComment = pScChangeAction->GetComment().replaceAll("\n""");
        if (!aDesc.isEmpty())
        {
            aComment += " (" + aDesc + ")";
        }
        if (pTheView->IsValidComment(aComment))
        {
            weld::TreeView& rTreeView = pTheView->GetWidget();
            xEntry = rTreeView.make_iterator();
            OUString sId(weld::toId(pNewData.release()));
            rTreeView.insert(pParent, -1, &aActionString, &sId, nullptr, nullptr, bCreateOnDemand, xEntry.get());

            OUString aRefStr = pScChangeAction->GetRefString(*pDoc, true);
            rTreeView.set_text(*xEntry, aRefStr, 1);

            if (!bIsGenerated)
            {
                rTreeView.set_text(*xEntry, aUser, 2);
                OUString sDate = ScGlobal::getLocaleData().getDate(aDateTime) + " " + ScGlobal::getLocaleData().getTime(aDateTime);
                rTreeView.set_text(*xEntry, sDate, 3);
            }

            rTreeView.set_text(*xEntry, aComment, 4);
        }
    }
    return xEntry;
}

std::unique_ptr<weld::TreeIter> ScAcceptChgDlg::InsertChangeActionContent(const ScChangeActionContent* pScChangeAction,
                                                                          const weld::TreeIter& rParent, sal_uLong nSpecial)
{
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();

    if(pScChangeAction==nullptr || pChanges==nullptr) return nullptr;

    bool bIsGenerated = pChanges->IsGenerated(pScChangeAction->GetActionNumber());

    bool bFlag = false;

    ScRange aRef=pScChangeAction->GetBigRange().MakeRange(*pDoc);
    OUString aUser=pScChangeAction->GetUser();
    DateTime aDateTime=pScChangeAction->GetDateTime();

    if (pTheView->IsValidEntry(aUser, aDateTime) || bIsGenerated)
    {
        if(pTPFilter->IsRange())
        {
            for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i )
            {
                ScRange const & rRangeEntry = aRangeList[ i ];
                if( rRangeEntry.Intersects(aRef) )
                {
                    bFlag=true;
                    break;
                }
            }
        }
        else if(!bIsGenerated)
            bFlag=true;
    }

    OUString aContent;
    OUString aRefStr;
    OUString aDate;
    OUString aDesc;

    if(nSpecial==RD_SPECIAL_CONTENT)
    {
        aContent = pScChangeAction->GetOldString(*pDoc);
        if (aContent.isEmpty())
            aContent = aStrEmpty;
        aDesc = aStrChildOrgContent + ": " + aContent;
    }
    else
    {
        const OUString aTmp( pScChangeAction->GetNewString(*pDoc));
        if (aTmp.isEmpty())
            aContent = aStrEmpty;
        else
            aContent = "\'" + aTmp + "\'";
        aDesc = aStrChildContent + aContent;
    }

    aRefStr = pScChangeAction->GetRefString(*pDoc, true);

    if(!bIsGenerated)
    {
        // aUser is kept.
        aDate = ScGlobal::getLocaleData().getDate(aDateTime) + " " + ScGlobal::getLocaleData().getTime(aDateTime);
    }
    else
    {
        aUser.clear();
    }

    OUString aComment = pScChangeAction->GetComment().replaceAll("\n""");

    if(!aDesc.isEmpty())
    {
        aComment += " (" + aDesc + ")";
    }

    std::unique_ptr<ScRedlinData> pNewData(new ScRedlinData);
    pNewData->nInfo=nSpecial;
    pNewData->pData=const_cast<ScChangeActionContent *>(pScChangeAction);
    pNewData->nActionNo=pScChangeAction->GetActionNumber();
    pNewData->bIsAcceptable=pScChangeAction->IsClickable();
    pNewData->bIsRejectable=false;
    pNewData->bDisabled=!pNewData->bIsAcceptable;
    pNewData->aDateTime=aDateTime;
    pNewData->nRow  = aRef.aStart.Row();
    pNewData->nCol  = aRef.aStart.Col();
    pNewData->nTable= aRef.aStart.Tab();

    weld::TreeView& rTreeView = pTheView->GetWidget();
    std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
    OUString sId(weld::toId(pNewData.release()));
    rTreeView.insert(&rParent, -1, &aContent, &sId, nullptr, nullptr, false, xEntry.get());
    rTreeView.set_text( *xEntry, aRefStr, 1);
    if (!aUser.isEmpty())
        rTreeView.set_text( *xEntry, aUser, 2);
    if (!aDate.isEmpty())
        rTreeView.set_text( *xEntry, aDate, 3);
    if (!aComment.isEmpty())
        rTreeView.set_text( *xEntry, aComment, 4);
    if (pTheView->IsValidComment(aComment) && bFlag)
        bHasFilterEntry=true;
    else
    {
        rTreeView.set_font_color(*xEntry, COL_LIGHTBLUE);
    }
    return xEntry;
}

void ScAcceptChgDlg::UpdateView()
{
    std::unique_ptr<weld::TreeIter> xParent;
    ScChangeTrack* pChanges=nullptr;
    const ScChangeAction* pScChangeAction=nullptr;
    m_xDialog->set_busy_cursor(true);
    weld::TreeView& rTreeView = pTheView->GetWidget();
    rTreeView.freeze();
    bool bFilterFlag = pTPFilter->IsDate() || pTPFilter->IsRange() ||
        pTPFilter->IsAuthor() || pTPFilter->IsComment();

    bUseColor = bFilterFlag;

    pChanges=pDoc->GetChangeTrack();
    if(pChanges!=nullptr)
        pScChangeAction=pChanges->GetFirst();
    bool bTheFlag = false;

    while(pScChangeAction!=nullptr)
    {
        bHasFilterEntry=false;
        switch (pScChangeAction->GetState())
        {
            case SC_CAS_VIRGIN:

                if (pScChangeAction->IsDialogRoot())
                {
                    bool bOnDemandChildren = !bFilterFlag && pScChangeAction->IsDialogParent();
                    if (pScChangeAction->IsDialogParent())
                        xParent = AppendChangeAction(pScChangeAction, bOnDemandChildren);
                    else
                        xParent = AppendFilteredAction(pScChangeAction, SC_CAS_VIRGIN, bOnDemandChildren);
                }
                else
                    xParent.reset();

                bTheFlag=true;
                break;

            case SC_CAS_ACCEPTED:
                xParent.reset();
                nAcceptCount++;
                break;

            case SC_CAS_REJECTED:
                xParent.reset();
                nRejectCount++;
                break;
        }

        if (xParent && pScChangeAction->IsDialogParent() && bFilterFlag)
        {
            bool bTestFlag = bHasFilterEntry;
            bHasFilterEntry=false;
            if (Expand(pChanges, pScChangeAction, *xParent, !bTestFlag) && !bTestFlag)
                rTreeView.remove(*xParent);
        }

        pScChangeAction=pScChangeAction->GetNext();
    }

    if( bTheFlag && (!pDoc->IsDocEditable() || pChanges->IsProtected()) )
        bTheFlag=false;

    pTPView->EnableAccept(bTheFlag);
    pTPView->EnableAcceptAll(bTheFlag);
    pTPView->EnableReject(bTheFlag);
    pTPView->EnableRejectAll(bTheFlag);

    if (nAcceptCount>0)
        rTreeView.insert(nullptr, -1, &aStrAllAccepted, nullptr, nullptr, nullptr, true, nullptr);
    if (nRejectCount>0)
        rTreeView.insert(nullptr, -1, &aStrAllRejected, nullptr, nullptr, nullptr, true, nullptr);
    rTreeView.thaw();
    m_xDialog->set_busy_cursor(false);
    std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
    if (rTreeView.get_iter_first(*xEntry))
        rTreeView.select(*xEntry);
}

IMPL_LINK_NOARG(ScAcceptChgDlg, RefHandle, SvxTPFilter*, void)
{
    sal_uInt16 nId  =ScSimpleRefDlgWrapper::GetChildWindowId();

    ScModule::get()->SetRefDialog(nId, true);

    SfxViewFrame& rViewFrm = pViewData->GetViewShell()->GetViewFrame();
    ScSimpleRefDlgWrapper* pWnd = static_cast<ScSimpleRefDlgWrapper*>(rViewFrm.GetChildWindow( nId ));

    if(pWnd!=nullptr)
    {
        sal_uInt16 nAcceptId=ScAcceptChgDlgWrapper::GetChildWindowId();
        rViewFrm.ShowChildWindow(nAcceptId,false);
        pWnd->SetCloseHdl(LINK( this, ScAcceptChgDlg,RefInfoHandle));
        pWnd->SetRefString(pTPFilter->GetRange());
        ScSimpleRefDlgWrapper::SetAutoReOpen(false);
        auto xWin = pWnd->GetController();
        m_xDialog->hide();
        xWin->set_title(m_xDialog->get_title());
        pWnd->StartRefInput();
    }
}

IMPL_LINK( ScAcceptChgDlg, RefInfoHandle, const OUString*, pResult, void)
{
    sal_uInt16 nId = ScAcceptChgDlgWrapper::GetChildWindowId();

    ScSimpleRefDlgWrapper::SetAutoReOpen(true);

    SfxViewFrame& rViewFrm = pViewData->GetViewShell()->GetViewFrame();
    if (pResult)
    {
        pTPFilter->SetRange(*pResult);
        FilterHandle(pTPFilter);

        rViewFrm.ShowChildWindow(nId);
    }
    else
    {
        rViewFrm.SetChildWindow(nId, false);
    }
}

IMPL_LINK( ScAcceptChgDlg, FilterHandle, SvxTPFilter*, pRef, void )
{
    if(pRef!=nullptr)
    {
        ClearView();
        aRangeList.RemoveAll();
        aRangeList.Parse(pTPFilter->GetRange(), *pDoc);
        UpdateView();
    }
}

IMPL_LINK( ScAcceptChgDlg, RejectHandle, SvxTPView*, pRef, void )
{
    m_xDialog->set_busy_cursor(true);

    bIgnoreMsg=true;
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();

    if(pRef!=nullptr)
    {
        weld::TreeView& rTreeView = pTheView->GetWidget();
        rTreeView.selected_foreach([this, pChanges, &rTreeView](weld::TreeIter& rEntry){
            ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rEntry));
            if (pEntryData)
            {
                ScChangeAction* pScChangeAction= static_cast<ScChangeAction*>(pEntryData->pData);
                if (pScChangeAction->GetType()==SC_CAT_INSERT_TABS)
                    pViewData->SetTabNo(0);
                pChanges->Reject(pScChangeAction);
            }
            return false;
        });
        ScDocShell& rDocSh=pViewData->GetDocShell();
        rDocSh.PostPaintExtras();
        rDocSh.PostPaintGridAll();
        rDocSh.GetUndoManager()->Clear();
        rDocSh.SetDocumentModified();
        ClearView();
        UpdateView();
    }

    m_xDialog->set_busy_cursor(false);

    bIgnoreMsg=false;
}
IMPL_LINK( ScAcceptChgDlg, AcceptHandle, SvxTPView*, pRef, void )
{
    m_xDialog->set_busy_cursor(true);

    ScChangeTrack* pChanges=pDoc->GetChangeTrack();
    bIgnoreMsg=true;
    if(pRef!=nullptr)
    {
        weld::TreeView& rTreeView = pTheView->GetWidget();
        rTreeView.selected_foreach([pChanges, &rTreeView](weld::TreeIter& rEntry) {
            ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rEntry));
            if (pEntryData)
            {
                ScChangeAction* pScChangeAction=
                        static_cast<ScChangeAction*>(pEntryData->pData);
                if(pScChangeAction->GetType()==SC_CAT_CONTENT)
                {
                    if(pEntryData->nInfo==RD_SPECIAL_CONTENT)
                        pChanges->SelectContent(pScChangeAction,true);
                    else
                        pChanges->SelectContent(pScChangeAction);
                }
                else
                    pChanges->Accept(pScChangeAction);
            }
            return false;
        });
        ScDocShell& rDocSh=pViewData->GetDocShell();
        rDocSh.PostPaintExtras();
        rDocSh.PostPaintGridAll();
        rDocSh.SetDocumentModified();
        ClearView();
        UpdateView();
    }
    m_xDialog->set_busy_cursor(false);
    bIgnoreMsg=false;
}

void ScAcceptChgDlg::RejectFiltered()
{
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();
    const ScChangeAction* pScChangeAction=nullptr;

    if(pChanges!=nullptr)
    {
        pScChangeAction=pChanges->GetLast();
    }

    while(pScChangeAction!=nullptr)
    {
        if(pScChangeAction->IsDialogRoot())
            if(IsValidAction(pScChangeAction))
                pChanges->Reject(const_cast<ScChangeAction*>(pScChangeAction));

        pScChangeAction=pScChangeAction->GetPrev();
    }
}
void ScAcceptChgDlg::AcceptFiltered()
{
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();
    const ScChangeAction* pScChangeAction=nullptr;

    if(pChanges!=nullptr)
        pScChangeAction=pChanges->GetLast();

    while(pScChangeAction!=nullptr)
    {
        if(pScChangeAction->IsDialogRoot())
            if(IsValidAction(pScChangeAction))
                pChanges->Accept(const_cast<ScChangeAction*>(pScChangeAction));

        pScChangeAction=pScChangeAction->GetPrev();
    }
}

IMPL_LINK_NOARG(ScAcceptChgDlg, RejectAllHandle, SvxTPView*, void)
{
    m_xDialog->set_busy_cursor(true);
    bIgnoreMsg=true;
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();
    if(pChanges!=nullptr)
    {
        if(pTPFilter->IsDate()||pTPFilter->IsAuthor()||pTPFilter->IsRange()||pTPFilter->IsComment())
            RejectFiltered();
        else
            pChanges->RejectAll();

        pViewData->SetTabNo(0);

        ScDocShell& rDocSh=pViewData->GetDocShell();
        rDocSh.PostPaintExtras();
        rDocSh.PostPaintGridAll();
        rDocSh.GetUndoManager()->Clear();
        rDocSh.SetDocumentModified();
        ClearView();
        UpdateView();
    }
    m_xDialog->set_busy_cursor(false);

    bIgnoreMsg=false;
}

IMPL_LINK_NOARG(ScAcceptChgDlg, AcceptAllHandle, SvxTPView*, void)
{
    m_xDialog->set_busy_cursor(true);

    bIgnoreMsg=true;
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();
    if(pChanges!=nullptr)
    {
        if(pTPFilter->IsDate()||pTPFilter->IsAuthor()||pTPFilter->IsRange()||pTPFilter->IsComment())
            AcceptFiltered();
        else
            pChanges->AcceptAll();

        ScDocShell& rDocSh=pViewData->GetDocShell();
        rDocSh.PostPaintExtras();
        rDocSh.PostPaintGridAll();
        rDocSh.SetDocumentModified();
        ClearView();
        UpdateView();
    }
    bIgnoreMsg=false;

    m_xDialog->set_busy_cursor(false);
}

IMPL_LINK_NOARG(ScAcceptChgDlg, SelectHandle, weld::TreeView&, void)
{
    if (!bNoSelection)
        aSelectionIdle.Start();

    bNoSelection=false;
}

void ScAcceptChgDlg::GetDependents(const ScChangeAction* pScChangeAction,
                                   ScChangeActionMap& aActionMap,
                                   const weld::TreeIter& rEntry)
{
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();

    weld::TreeView& rTreeView = pTheView->GetWidget();
    std::unique_ptr<weld::TreeIter> xParent(rTreeView.make_iterator(&rEntry));
    if (rTreeView.iter_parent(*xParent))
    {
        ScRedlinData *pParentData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xParent));
        ScChangeAction* pParentAction=static_cast<ScChangeAction*>(pParentData->pData);

        if(pParentAction!=pScChangeAction)
            pChanges->GetDependents(const_cast<ScChangeAction*>(pScChangeAction),
                        aActionMap,pScChangeAction->IsMasterDelete());
        else
            pChanges->GetDependents( const_cast<ScChangeAction*>(pScChangeAction),
                        aActionMap );
    }
    else
        pChanges->GetDependents(const_cast<ScChangeAction*>(pScChangeAction),
                    aActionMap, pScChangeAction->IsMasterDelete() );
}

bool ScAcceptChgDlg::InsertContentChildren(ScChangeActionMap* pActionMap, const weld::TreeIter& rParent)
{
    bool bTheTestFlag = true;
    weld::TreeView& rTreeView = pTheView->GetWidget();
    ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rParent));
    const ScChangeAction* pScChangeAction = static_cast<ScChangeAction*>(pEntryData->pData);
    bool bParentInserted = false;
    // If the parent is a MatrixOrigin then place it in the right order before
    // the MatrixReferences. Also if it is the first content change at this
    // position don't insert the first dependent MatrixReference as the special
    // content (original value) but insert the predecessor of the MatrixOrigin
    // itself instead.
    if ( pScChangeAction->GetType() == SC_CAT_CONTENT &&
            static_cast<const ScChangeActionContent*>(pScChangeAction)->IsMatrixOrigin() )
    {
        pActionMap->insert( ::std::make_pair( pScChangeAction->GetActionNumber(),
            const_cast<ScChangeAction*>( pScChangeAction ) ) );
        bParentInserted = true;
    }

    ScChangeActionMap::iterator itChangeAction = std::find_if(pActionMap->begin(), pActionMap->end(),
        [](const std::pair<sal_uLong, ScChangeAction*>& rEntry) { return rEntry.second->GetState() == SC_CAS_VIRGIN; });

    if( itChangeAction == pActionMap->end() )
        return true;

    std::unique_ptr<weld::TreeIter> xOriginal = InsertChangeActionContent(
        dynamic_cast<const ScChangeActionContent*>( itChangeAction->second ),
        rParent, RD_SPECIAL_CONTENT );

    if (xOriginal)
    {
        bTheTestFlag=false;
        ScRedlinData *pParentData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xOriginal));
        pParentData->pData=const_cast<ScChangeAction *>(pScChangeAction);
        pParentData->nActionNo=pScChangeAction->GetActionNumber();
        pParentData->bIsAcceptable=pScChangeAction->IsRejectable(); // select old value
        pParentData->bIsRejectable=false;
        pParentData->bDisabled=false;
    }
    while( itChangeAction != pActionMap->end() )
    {
        if( itChangeAction->second->GetState() == SC_CAS_VIRGIN )
        {
            std::unique_ptr<weld::TreeIter> xEntry =
                InsertChangeActionContent( dynamic_cast<const ScChangeActionContent*>( itChangeAction->second ),
                    rParent, RD_SPECIAL_NONE );

            if (xEntry)
                bTheTestFlag=false;
        }
        ++itChangeAction;
    }

    if ( !bParentInserted )
    {
        std::unique_ptr<weld::TreeIter> xEntry =
            InsertChangeActionContent(static_cast<const ScChangeActionContent*>(
                                pScChangeAction),rParent,RD_SPECIAL_NONE);

        if (xEntry)
        {
            bTheTestFlag=false;
            ScRedlinData *pParentData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
            pParentData->pData=const_cast<ScChangeAction *>(pScChangeAction);
            pParentData->nActionNo=pScChangeAction->GetActionNumber();
            pParentData->bIsAcceptable=pScChangeAction->IsClickable();
            pParentData->bIsRejectable=false;
            pParentData->bDisabled=false;
        }
    }

    return bTheTestFlag;
}

bool ScAcceptChgDlg::InsertAcceptedORejected(const weld::TreeIter& rParent)
{
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();
    bool bTheTestFlag = true;

    ScChangeActionState eState = SC_CAS_VIRGIN;
    weld::TreeView& rTreeView = pTheView->GetWidget();
    OUString aString = rTreeView.get_text(rParent, 0);
    OUString a2String = aString.copy(0, aStrAllAccepted.getLength());
    if (a2String == aStrAllAccepted)
        eState=SC_CAS_ACCEPTED;
    else
    {
        a2String = aString.copy(0, aStrAllRejected.getLength());
        if (a2String == aStrAllRejected)
            eState=SC_CAS_REJECTED;
    }

    ScChangeAction* pScChangeAction = pChanges->GetFirst();
    while (pScChangeAction)
    {
        if (pScChangeAction->GetState()==eState &&
            AppendFilteredAction(pScChangeAction, eState, false, &rParent))
            bTheTestFlag=false;
        pScChangeAction=pScChangeAction->GetNext();
    }
    return bTheTestFlag;
}

bool ScAcceptChgDlg::InsertChildren(ScChangeActionMap* pActionMap, const weld::TreeIter& rParent)
{
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();
    bool bTheTestFlag = true;

    forconst auto& rChangeAction : *pActionMap )
    {
        std::unique_ptr<weld::TreeIter> xEntry = AppendChangeAction(rChangeAction.second, false, &rParent, falsetrue);

        if (xEntry)
        {
            bTheTestFlag=false;

            weld::TreeView& rTreeView = pTheView->GetWidget();
            ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
            pEntryData->bIsRejectable=false;
            pEntryData->bIsAcceptable=false;
            pEntryData->bDisabled=true;

            if (rChangeAction.second->IsDialogParent())
                Expand(pChanges, rChangeAction.second, *xEntry);
        }
    }
    return bTheTestFlag;
}

bool ScAcceptChgDlg::InsertDeletedChildren(const ScChangeAction* pScChangeAction,
                                           ScChangeActionMap* pActionMap, const weld::TreeIter& rParent)
{
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();
    bool bTheTestFlag = true;
    std::unique_ptr<weld::TreeIter> xEntry;

    forconst auto& rChangeAction : *pActionMap )
    {

        if( pScChangeAction != rChangeAction.second )
            xEntry = AppendChangeAction(rChangeAction.second, false, &rParent, falsetrue);
        else
            xEntry = AppendChangeAction(rChangeAction.second, false, &rParent, truetrue);

        if (xEntry)
        {
            weld::TreeView& rTreeView = pTheView->GetWidget();
            ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
            pEntryData->bIsRejectable=false;
            pEntryData->bIsAcceptable=false;
            pEntryData->bDisabled=true;

            bTheTestFlag=false;

            if (rChangeAction.second->IsDialogParent())
                Expand(pChanges, rChangeAction.second, *xEntry);
        }
    }
    return bTheTestFlag;
}

bool ScAcceptChgDlg::Expand(const ScChangeTrack* pChanges, const ScChangeAction* pScChangeAction,
                            const weld::TreeIter& rEntry, bool bFilter)
{
    bool bTheTestFlag = true;

    if (pChanges && pScChangeAction)
    {
        ScChangeActionMap aActionMap;

        GetDependents(pScChangeAction, aActionMap, rEntry);

        switch(pScChangeAction->GetType())
        {
            case SC_CAT_CONTENT:
            {
                InsertContentChildren(&aActionMap, rEntry);
                bTheTestFlag=!bHasFilterEntry;
                break;
            }
            case SC_CAT_DELETE_COLS:
            case SC_CAT_DELETE_ROWS:
            case SC_CAT_DELETE_TABS:
            {
                InsertDeletedChildren(pScChangeAction, &aActionMap, rEntry);
                bTheTestFlag=!bHasFilterEntry;
                break;
            }
            default:
            {
                if(!bFilter)
                    bTheTestFlag = InsertChildren(&aActionMap, rEntry);
                break;
            }
        }
        aActionMap.clear();
    }
    return bTheTestFlag;
}

IMPL_LINK(ScAcceptChgDlg, ExpandingHandle, const weld::TreeIter&, rEntry, bool)
{
    ScChangeTrack* pChanges=pDoc->GetChangeTrack();
    if (pChanges)
    {
        m_xDialog->set_busy_cursor(true);
        ScChangeActionMap aActionMap;
        weld::TreeView& rTreeView = pTheView->GetWidget();
        ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rEntry));
        if (!rTreeView.iter_has_child(rEntry))
        {
            bool bTheTestFlag = true;

            if (pEntryData)
            {
                ScChangeAction* pScChangeAction=static_cast<ScChangeAction*>(pEntryData->pData);

                GetDependents(pScChangeAction, aActionMap, rEntry);

                switch (pScChangeAction->GetType())
                {
                    case SC_CAT_CONTENT:
                    {
                        bTheTestFlag = InsertContentChildren( &aActionMap, rEntry );
                        break;
                    }
                    case SC_CAT_DELETE_COLS:
                    case SC_CAT_DELETE_ROWS:
                    case SC_CAT_DELETE_TABS:
                    {
                        bTheTestFlag = InsertDeletedChildren( pScChangeAction, &aActionMap, rEntry );
                        break;
                    }
                    default:
                    {
                        bTheTestFlag = InsertChildren( &aActionMap, rEntry );
                        break;
                    }
                }
                aActionMap.clear();

            }
            else
            {
                bTheTestFlag = InsertAcceptedORejected(rEntry);
            }
            if (bTheTestFlag)
            {
                std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
                rTreeView.insert(&rEntry, -1, &aStrNoEntry, nullptr, nullptr, nullptr, false, xEntry.get());
                rTreeView.set_font_color(*xEntry, COL_GRAY);
            }
        }
        m_xDialog->set_busy_cursor(false);
    }
    return true;
}

void ScAcceptChgDlg::AppendChanges(const ScChangeTrack* pChanges,sal_uLong nStartAction,
                                   sal_uLong nEndAction)
{
    if(pChanges==nullptr)
        return;

    std::unique_ptr<weld::TreeIter> xParent;
    m_xDialog->set_busy_cursor(true);
    weld::TreeView& rTreeView = pTheView->GetWidget();
    rTreeView.freeze();

    bool bTheFlag = false;

    bool bFilterFlag = pTPFilter->IsDate() || pTPFilter->IsRange() ||
        pTPFilter->IsAuthor() || pTPFilter->IsComment();

    bUseColor = bFilterFlag;

    for(sal_uLong i=nStartAction;i<=nEndAction;i++)
    {
        const ScChangeAction* pScChangeAction=pChanges->GetAction(i);
        if(pScChangeAction==nullptr) continue;

        switch (pScChangeAction->GetState())
        {
            case SC_CAS_VIRGIN:

                if (pScChangeAction->IsDialogRoot())
                {
                    bool bOnDemandChildren = !bFilterFlag && pScChangeAction->IsDialogParent();
                    if (pScChangeAction->IsDialogParent())
                        xParent = AppendChangeAction(pScChangeAction, bOnDemandChildren);
                    else
                        xParent = AppendFilteredAction(pScChangeAction, SC_CAS_VIRGIN, bOnDemandChildren);
                }
                else
                    xParent.reset();

                bTheFlag=true;
                break;

            case SC_CAS_ACCEPTED:
                xParent.reset();
                nAcceptCount++;
                break;

            case SC_CAS_REJECTED:
                xParent.reset();
                nRejectCount++;
                break;
        }

        if (xParent && pScChangeAction->IsDialogParent() && bFilterFlag)
        {
            bool bTestFlag = bHasFilterEntry;
            bHasFilterEntry = false;
            if (Expand(pChanges,pScChangeAction,*xParent,!bTestFlag)&&!bTestFlag)
                rTreeView.remove(*xParent);
        }
    }

    if( bTheFlag && (!pDoc->IsDocEditable() || pChanges->IsProtected()) )
        bTheFlag=false;

    pTPView->EnableAccept(bTheFlag);
    pTPView->EnableAcceptAll(bTheFlag);
    pTPView->EnableReject(bTheFlag);
    pTPView->EnableRejectAll(bTheFlag);

    rTreeView.thaw();
    m_xDialog->set_busy_cursor(false);
}

void ScAcceptChgDlg::RemoveEntries(sal_uLong nStartAction,sal_uLong nEndAction)
{
    weld::TreeView& rTreeView = pTheView->GetWidget();

    ScRedlinData *pEntryData=nullptr;
    std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
    if (rTreeView.get_cursor(xEntry.get()))
        pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));

    if (!rTreeView.get_iter_first(*xEntry))
        return;

    sal_uLong nAction=0;
    if (pEntryData)
        nAction=pEntryData->nActionNo;

    if (nAction>=nStartAction && nAction<=nEndAction)
        rTreeView.set_cursor(*xEntry);

    std::vector<OUString> aIdsToRemove;

    do
    {
        OUString sId(rTreeView.get_id(*xEntry));
        pEntryData = weld::fromId<ScRedlinData*>(sId);
        if (pEntryData)
        {
            nAction = pEntryData->nActionNo;
            if (nStartAction <= nAction && nAction <= nEndAction)
            {
                aIdsToRemove.push_back(sId);
                delete pEntryData;
            }
        }
    }
    while (rTreeView.iter_next(*xEntry));

    rTreeView.freeze();

    // MUST do it backwards, don't delete parents before children and GPF
    for (auto it = aIdsToRemove.rbegin(); it != aIdsToRemove.rend(); ++it)
        rTreeView.remove_id(*it);

    rTreeView.thaw();
}

void ScAcceptChgDlg::UpdateEntries(const ScChangeTrack* pChgTrack, sal_uLong nStartAction,sal_uLong nEndAction)
{
    weld::TreeView& rTreeView = pTheView->GetWidget();
    rTreeView.freeze();

    std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
    std::unique_ptr<weld::TreeIter> xLastEntry(rTreeView.make_iterator());
    std::unique_ptr<weld::TreeIter> xNextEntry(rTreeView.make_iterator());

    bool bEntry = rTreeView.get_iter_first(*xEntry);
    bool bLastEntry = false;

    while (bEntry)
    {
        bool bRemove = false;
        ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
        if (pEntryData)
        {
            ScChangeAction* pScChangeAction=
                    static_cast<ScChangeAction*>(pEntryData->pData);

            sal_uLong nAction=pScChangeAction->GetActionNumber();

            if(nStartAction<=nAction && nAction<=nEndAction) bRemove=true;
        }

        bool bNextEntry;
        if (bRemove)
        {
            rTreeView.remove(*xEntry);
            delete pEntryData;

            if (!bLastEntry)
                bLastEntry = rTreeView.get_iter_first(*xLastEntry);
            if (bLastEntry)
            {
                rTreeView.copy_iterator(*xLastEntry, *xNextEntry);
                bNextEntry = rTreeView.iter_next(*xNextEntry);
                if (!bNextEntry)
                {
                    rTreeView.copy_iterator(*xLastEntry, *xNextEntry);
                    bLastEntry = false;
                }
            }
            else
                bNextEntry = false;
        }
        else
        {
            rTreeView.copy_iterator(*xEntry, *xLastEntry);
            bLastEntry = true;

            rTreeView.copy_iterator(*xEntry, *xNextEntry);
            bNextEntry = rTreeView.iter_next(*xNextEntry);
        }

        rTreeView.copy_iterator(*xNextEntry, *xEntry);
        bEntry = bNextEntry;
    }

    AppendChanges(pChgTrack,nStartAction,nEndAction);

    rTreeView.thaw();
}

IMPL_LINK( ScAcceptChgDlg, ChgTrackModHdl, ScChangeTrack&, rChgTrack, void)
{
    ScChangeTrackMsgQueue& aMsgQueue= rChgTrack.GetMsgQueue();

    sal_uLong   nStartAction;
    sal_uLong   nEndAction;

    for (const auto& rMsg : aMsgQueue)
    {
        nStartAction = rMsg.nStartAction;
        nEndAction = rMsg.nEndAction;

        if(!bIgnoreMsg)
        {
            bNoSelection=true;

            switch(rMsg.eMsgType)
            {
                case ScChangeTrackMsgType::Append:
                                    AppendChanges(&rChgTrack,nStartAction,nEndAction);
                                    break;
                case ScChangeTrackMsgType::Remove:
                                    RemoveEntries(nStartAction,nEndAction);
                                    break;
                case ScChangeTrackMsgType::Parent:
                case ScChangeTrackMsgType::Change: //bNeedsUpdate=true;
                                    UpdateEntries(&rChgTrack,nStartAction,nEndAction);
                                    break;
                default: assert(false); break;
            }
        }
    }

    aMsgQueue.clear();
}

IMPL_LINK_NOARG(ScAcceptChgDlg, ReOpenTimerHdl, Timer *, void)
{
    ScSimpleRefDlgWrapper::SetAutoReOpen(true);
    m_xAcceptChgCtr->ShowFilterPage();
    RefHandle(nullptr);
}

IMPL_LINK_NOARG(ScAcceptChgDlg, UpdateSelectionHdl, Timer *, void)
{
    ScTabView* pTabView = pViewData->GetView();

    bool bAcceptFlag = true;
    bool bRejectFlag = true;

    pTabView->DoneBlockMode();  // clears old marking
    weld::TreeView& rTreeView = pTheView->GetWidget();
    std::vector<const ScChangeAction*> aActions;
    rTreeView.selected_foreach([&rTreeView, &bAcceptFlag, &bRejectFlag, &aActions](weld::TreeIter& rEntry){
        ScRedlinData* pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rEntry));
        if (pEntryData)
        {
            bRejectFlag &= pEntryData->bIsRejectable;
            bAcceptFlag &= pEntryData->bIsAcceptable;

            const ScChangeAction* pScChangeAction = static_cast<ScChangeAction*>(pEntryData->pData);
            if( pScChangeAction && (pScChangeAction->GetType() != SC_CAT_DELETE_TABS) &&
                    (!pEntryData->bDisabled || pScChangeAction->IsVisible()) )
            {
                aActions.push_back(pScChangeAction);
            }
        }
        else
        {
            bAcceptFlag = false;
            bRejectFlag = false;
        }
        return false;
    });

    bool bContMark = false;
    for (size_t i = 0, nCount = aActions.size(); i < nCount; ++i)
    {
        const ScBigRange& rBigRange = aActions[i]->GetBigRange();
        if (rBigRange.IsValid(*pDoc) && m_xDialog->has_toplevel_focus())
        {
            bool bSetCursor = i == nCount - 1;
            pTabView->MarkRange(rBigRange.MakeRange(*pDoc), bSetCursor, bContMark);
            bContMark = true;
        }
    }

    ScChangeTrack* pChanges = pDoc->GetChangeTrack();
    bool bEnable = pDoc->IsDocEditable() && pChanges && !pChanges->IsProtected();
    pTPView->EnableAccept( bAcceptFlag && bEnable );
    pTPView->EnableReject( bRejectFlag && bEnable );
}

IMPL_LINK(ScAcceptChgDlg, CommandHdl, const CommandEvent&, rCEvt, bool)
{
    if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
        return false;

    weld::TreeView& rTreeView = pTheView->GetWidget();
    std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
    bool bEntry = rTreeView.get_cursor(xEntry.get());
    if (bEntry)
        rTreeView.select(*xEntry);

    int nSortedCol = rTreeView.get_sort_column();
    for (sal_Int32 i = 0; i < 5; ++i)
        m_xSortMenu->set_active("calcsort" + OUString::number(i), i == nSortedCol);

    m_xPopup->set_sensitive(u"calcedit"_ustr, false);

    if (pDoc->IsDocEditable() && bEntry)
    {
        ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
        if (pEntryData)
        {
            ScChangeAction* pScChangeAction = static_cast<ScChangeAction*>(pEntryData->pData);
            if (pScChangeAction && !rTreeView.get_iter_depth(*xEntry))
                m_xPopup->set_sensitive(u"calcedit"_ustr, true);
        }
    }

    OUString sCommand = m_xPopup->popup_at_rect(&rTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));

    if (!sCommand.isEmpty())
    {
        if (sCommand == "calcedit")
        {
            if (bEntry)
            {
                ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
                if (pEntryData)
                {
                    ScChangeAction* pScChangeAction = static_cast<ScChangeAction*>(pEntryData->pData);
                    pViewData->GetDocShell().ExecuteChangeCommentDialog(pScChangeAction, m_xDialog.get(), false);
                }
            }
        }
        else
        {
            int nDialogCol = o3tl::toInt32(sCommand.subView(8));
            pTheView->HeaderBarClick(nDialogCol);
        }
    }

    return true;
}

namespace
{
    //at one point we were writing multiple AcceptChgDat strings,
    //so strip all of them and keep the results of the last one
    OUString lcl_StripAcceptChgDat(OUString &rExtraString)
    {
        OUString aStr;
        while (true)
        {
            sal_Int32 nPos = rExtraString.indexOf("AcceptChgDat:");
            if (nPos == -1)
                break;
            // Try to read the alignment string "ALIGN:(...)"; if it is missing
            // we have an old version
            sal_Int32 n1 = rExtraString.indexOf('(', nPos);
            if ( n1 != -1 )
            {
                sal_Int32 n2 = rExtraString.indexOf(')', n1);
                if ( n2 != -1 )
                {
                    // cut out alignment string
                    aStr = rExtraString.copy(nPos, n2 - nPos + 1);
                    rExtraString = rExtraString.replaceAt(nPos, n2 - nPos + 1, u"");
                    aStr = aStr.copy( n1-nPos+1 );
                }
            }
        }
        return aStr;
    }
}

void ScAcceptChgDlg::Initialize(SfxChildWinInfo* pInfo)
{
    OUString aStr;
    if (pInfo && !pInfo->aExtraString.isEmpty())
        aStr = lcl_StripAcceptChgDat(pInfo->aExtraString);

    SfxModelessDialogController::Initialize(pInfo);

    if (aStr.isEmpty())
        return;

    int nCount = aStr.toInt32();
    if (nCount <= 2)
        return;

    std::vector<int> aEndPos;

    for (int i = 0; i < nCount; ++i)
    {
        sal_Int32 n1 = aStr.indexOf(';');
        aStr = aStr.copy( n1+1 );
        aEndPos.push_back(aStr.toInt32());
    }

    std::vector<int> aWidths;
    for (int i = 1; i < nCount; ++i)
        aWidths.push_back(aEndPos[i] - aEndPos[i - 1]);

    // turn column end points back to column widths, ignoring the small
    // value used for the expander column
    weld::TreeView& rTreeView = pTheView->GetWidget();
    rTreeView.set_column_fixed_widths(aWidths);
}

void ScAcceptChgDlg::FillInfo(SfxChildWinInfo& rInfo) const
{
    SfxModelessDialogController::FillInfo(rInfo);
    //remove any old one before adding a new one
    lcl_StripAcceptChgDat(rInfo.aExtraString);
    rInfo.aExtraString += "AcceptChgDat:(";

    const int nTabCount = 5;

    rInfo.aExtraString += OUString::number(nTabCount);
    rInfo.aExtraString += ";";

    weld::TreeView& rTreeView = pTheView->GetWidget();
    std::vector<int> aWidths;
    // turn column widths back into column end points for compatibility
    // with how they used to be stored, including a small value for the
    // expander column
    aWidths.push_back(rTreeView.get_checkbox_column_width());
    for (int i = 0; i < nTabCount - 1; ++i)
        aWidths.push_back(aWidths.back() + rTreeView.get_column_width(i));

    for (auto a : aWidths)
    {
        rInfo.aExtraString += OUString::number(a);
        rInfo.aExtraString += ";";
    }
    rInfo.aExtraString += ")";
}

#define CALC_DATE       3
#define CALC_POS        1

int ScAcceptChgDlg::ColCompareHdl(const weld::TreeIter& rLeft, const weld::TreeIter& rRight) const
{
    weld::TreeView& rTreeView = pTheView->GetWidget();

    sal_Int32 nCompare = 0;
    SCCOL nSortCol = rTreeView.get_sort_column();

    if (CALC_DATE == nSortCol)
    {
        RedlinData *pLeftData = weld::fromId<RedlinData*>(rTreeView.get_id(rLeft));
        RedlinData *pRightData = weld::fromId<RedlinData*>(rTreeView.get_id(rRight));
        if (pLeftData && pRightData)
        {
            if(pLeftData->aDateTime < pRightData->aDateTime)
                nCompare = -1;
            else if(pLeftData->aDateTime > pRightData->aDateTime)
                nCompare = 1;
            return nCompare;
        }
    }
    else if (CALC_POS == nSortCol)
    {
        ScRedlinData *pLeftData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rLeft));
        ScRedlinData *pRightData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rRight));
        if (pLeftData && pRightData)
        {
            nCompare = 1;

            if(pLeftData->nTable < pRightData->nTable)
                nCompare = -1;
            else if(pLeftData->nTable == pRightData->nTable)
            {
                if(pLeftData->nRow < pRightData->nRow)
                    nCompare = -1;
                else if(pLeftData->nRow == pRightData->nRow)
                {
                    if(pLeftData->nCol < pRightData->nCol)
                        nCompare = -1;
                    else if(pLeftData->nCol == pRightData->nCol)
                        nCompare = 0;
                }
            }

            return nCompare;
        }
    }

    return ScGlobal::GetCaseCollator().compareString(rTreeView.get_text(rLeft, nSortCol),
                                                      rTreeView.get_text(rRight, nSortCol));
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=95 H=88 G=91

¤ Dauer der Verarbeitung: 0.29 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.