1792 lines
57 KiB
C++
1792 lines
57 KiB
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* ptrViewData)
|
|
: SfxModelessDialogController(pB, pCW, pParent,
|
|
u"svx/ui/acceptrejectchangesdialog.ui"_ustr, u"AcceptRejectChangesDialog"_ustr)
|
|
, aSelectionIdle( "ScAcceptChgDlg aSelectionIdle" )
|
|
, aReOpenIdle("ScAcceptChgDlg ReOpenIdle")
|
|
, pViewData( ptrViewData )
|
|
, pDoc( &ptrViewData->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_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& 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* ptrViewData)
|
|
{
|
|
pViewData=ptrViewData;
|
|
if (pViewData)
|
|
pDoc = &ptrViewData->GetDocument();
|
|
else
|
|
pDoc = nullptr;
|
|
|
|
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();
|
|
|
|
if ( pDoc )
|
|
{
|
|
ScChangeTrack* pChanges = pDoc->GetChangeTrack();
|
|
if ( pChanges )
|
|
pChanges->SetModifiedLink( LINK( this, ScAcceptChgDlg, ChgTrackModHdl ) );
|
|
}
|
|
}
|
|
|
|
void ScAcceptChgDlg::Init()
|
|
{
|
|
OSL_ENSURE( pViewData && pDoc, "ViewData or Document not found!" );
|
|
|
|
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;
|
|
|
|
if(pDoc!=nullptr)
|
|
{
|
|
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* pDocSh=pViewData->GetDocShell();
|
|
pDocSh->PostPaintExtras();
|
|
pDocSh->PostPaintGridAll();
|
|
pDocSh->GetUndoManager()->Clear();
|
|
pDocSh->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* pDocSh=pViewData->GetDocShell();
|
|
pDocSh->PostPaintExtras();
|
|
pDocSh->PostPaintGridAll();
|
|
pDocSh->SetDocumentModified();
|
|
ClearView();
|
|
UpdateView();
|
|
}
|
|
m_xDialog->set_busy_cursor(false);
|
|
bIgnoreMsg=false;
|
|
}
|
|
|
|
void ScAcceptChgDlg::RejectFiltered()
|
|
{
|
|
if(pDoc==nullptr) return;
|
|
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()
|
|
{
|
|
if(pDoc==nullptr) return;
|
|
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* pDocSh=pViewData->GetDocShell();
|
|
pDocSh->PostPaintExtras();
|
|
pDocSh->PostPaintGridAll();
|
|
pDocSh->GetUndoManager()->Clear();
|
|
pDocSh->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* pDocSh=pViewData->GetDocShell();
|
|
pDocSh->PostPaintExtras();
|
|
pDocSh->PostPaintGridAll();
|
|
pDocSh->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;
|
|
|
|
for( const auto& rChangeAction : *pActionMap )
|
|
{
|
|
std::unique_ptr<weld::TreeIter> xEntry = AppendChangeAction(rChangeAction.second, false, &rParent, false, true);
|
|
|
|
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;
|
|
|
|
for( const auto& rChangeAction : *pActionMap )
|
|
{
|
|
|
|
if( pScChangeAction != rChangeAction.second )
|
|
xEntry = AppendChangeAction(rChangeAction.second, false, &rParent, false, true);
|
|
else
|
|
xEntry = AppendChangeAction(rChangeAction.second, false, &rParent, true, true);
|
|
|
|
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: */
|