blob: 75c1bb75d156485ab6749bf700b19880cb9cc2cb [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#define _SVSTDARR_STRINGSSORTDTOR
#define _SVSTDARR_USHORTSSORT
#define _SVSTDARR_USHORTS
#include <redline.hxx>
#include <tools/datetime.hxx>
#include <vcl/msgbox.hxx>
#include <svl/svstdarr.hxx>
#include <svl/eitem.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/dispatch.hxx>
#include <svx/ctredlin.hxx>
#include <svx/postattr.hxx>
#include <swtypes.hxx>
#include <wrtsh.hxx>
#include <view.hxx>
#include <swmodule.hxx>
#ifndef _REDLNDLG_HXX
#define _REDLNACCEPTDLG
#include <redlndlg.hxx>
#endif
#include <swwait.hxx>
#include <uitool.hxx>
#include <helpid.h>
#include <cmdid.h>
#include <misc.hrc>
#include <redlndlg.hrc>
#include <shells.hrc>
// -> #111827#
#include <comcore.hrc>
#include <swundo.hxx>
#include <SwRewriter.hxx>
// <- #111827#
#include <vector>
#include <svx/svxdlg.hxx>
#include <svx/dialogs.hrc>
#include <unomid.h>
#include <docsh.hxx>
#include <IDocumentRedlineAccess.hxx>
/*------------------------------------------------------------------------
Beschreibung:
------------------------------------------------------------------------*/
SFX_IMPL_MODELESSDIALOG( SwRedlineAcceptChild, FN_REDLINE_ACCEPT )
SV_IMPL_PTRARR(SwRedlineDataParentArr, SwRedlineDataParentPtr)
SV_IMPL_OP_PTRARR_SORT(SwRedlineDataParentSortArr, SwRedlineDataParentPtr)
SV_IMPL_PTRARR(SwRedlineDataChildArr, SwRedlineDataChildPtr)
SV_IMPL_PTRARR(SvLBoxEntryArr, SvLBoxEntryPtr)
static sal_uInt16 nSortMode = 0xffff;
static sal_Bool bSortDir = sal_True;
/*------------------------------------------------------------------------
Beschreibung:
------------------------------------------------------------------------*/
SwRedlineAcceptChild::SwRedlineAcceptChild( Window* _pParent,
sal_uInt16 nId,
SfxBindings* pBindings,
SfxChildWinInfo* pInfo ) :
SwChildWinWrapper( _pParent, nId )
{
pWindow = new SwModelessRedlineAcceptDlg( pBindings, this, _pParent);
((SwModelessRedlineAcceptDlg *)pWindow)->Initialize(pInfo);
}
/*--------------------------------------------------------------------
Beschreibung: Nach Dok-Wechsel Dialog neu initialisieren
--------------------------------------------------------------------*/
sal_Bool SwRedlineAcceptChild::ReInitDlg(SwDocShell *pDocSh)
{
sal_Bool bRet;
if ((bRet = SwChildWinWrapper::ReInitDlg(pDocSh)) == sal_True) // Sofort aktualisieren, Dok-Wechsel
((SwModelessRedlineAcceptDlg*)GetWindow())->Activate();
return bRet;
}
/*------------------------------------------------------------------------
Beschreibung:
------------------------------------------------------------------------*/
SwModelessRedlineAcceptDlg::SwModelessRedlineAcceptDlg( SfxBindings* _pBindings,
SwChildWinWrapper* pChild,
Window *_pParent) :
SfxModelessDialog(_pBindings, pChild, _pParent, SW_RES(DLG_REDLINE_ACCEPT)),
pChildWin (pChild)
{
pImplDlg = new SwRedlineAcceptDlg(this);
FreeResource();
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
void SwModelessRedlineAcceptDlg::Activate()
{
SwView *pView = ::GetActiveView();
if (!pView) // Kann passieren, wenn man auf eine andere App umschaltet, wenn
return; // vorher eine Listbox im Dialog den Focus hatte (eigentlich THs Bug)
SwDocShell *pDocSh = pView->GetDocShell();
if (pChildWin->GetOldDocShell() != pDocSh)
{ // Dok-Wechsel
SwWait aWait( *pDocSh, false );
SwWrtShell* pSh = pView->GetWrtShellPtr();
pChildWin->SetOldDocShell(pDocSh); // Rekursion vermeiden (durch Modified-Hdl)
sal_Bool bMod = pSh->IsModified();
SfxBoolItem aShow(FN_REDLINE_SHOW, sal_True);
pSh->GetView().GetViewFrame()->GetDispatcher()->Execute(
FN_REDLINE_SHOW, SFX_CALLMODE_SYNCHRON|SFX_CALLMODE_RECORD, &aShow, 0L);
if (!bMod)
pSh->ResetModified();
pImplDlg->Init();
return;
}
pImplDlg->Activate();
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
void SwModelessRedlineAcceptDlg::Initialize(SfxChildWinInfo *pInfo)
{
String aStr;
if (pInfo != NULL)
pImplDlg->Initialize(pInfo->aExtraString);
SfxModelessDialog::Initialize(pInfo);
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
void SwModelessRedlineAcceptDlg::FillInfo(SfxChildWinInfo& rInfo) const
{
SfxModelessDialog::FillInfo(rInfo);
pImplDlg->FillInfo(rInfo.aExtraString);
}
/*------------------------------------------------------------------------
Beschreibung:
------------------------------------------------------------------------*/
void SwModelessRedlineAcceptDlg::Resize()
{
pImplDlg->Resize();
SfxModelessDialog::Resize();
}
/*------------------------------------------------------------------------
Beschreibung:
------------------------------------------------------------------------*/
SwModelessRedlineAcceptDlg::~SwModelessRedlineAcceptDlg()
{
delete pImplDlg;
}
/*------------------------------------------------------------------------
Beschreibung:
------------------------------------------------------------------------*/
SwRedlineAcceptDlg::SwRedlineAcceptDlg(Dialog *pParent, sal_Bool bAutoFmt) :
pParentDlg (pParent),
aTabPagesCTRL (pParent, SW_RES(CTRL_TABPAGES)),
aPopup (SW_RES(MN_REDLINE_POPUP)),
sInserted (SW_RES(STR_REDLINE_INSERTED)),
sDeleted (SW_RES(STR_REDLINE_DELETED)),
sFormated (SW_RES(STR_REDLINE_FORMATED)),
sTableChgd (SW_RES(STR_REDLINE_TABLECHG)),
sFmtCollSet (SW_RES(STR_REDLINE_FMTCOLLSET)),
sAutoFormat (SW_RES(STR_REDLINE_AUTOFMT)),
bOnlyFormatedRedlines( sal_False ),
bHasReadonlySel ( sal_False ),
bRedlnAutoFmt (bAutoFmt),
bInhibitActivate( false )
{
aTabPagesCTRL.SetHelpId(HID_REDLINE_CTRL);
pTPView = aTabPagesCTRL.GetViewPage();
pTable = pTPView->GetTableControl();
pTPView->InsertWriterHeader();
pTPView->SetAcceptClickHdl(LINK(this, SwRedlineAcceptDlg, AcceptHdl));
pTPView->SetAcceptAllClickHdl(LINK(this, SwRedlineAcceptDlg, AcceptAllHdl));
pTPView->SetRejectClickHdl(LINK(this, SwRedlineAcceptDlg, RejectHdl));
pTPView->SetRejectAllClickHdl(LINK(this, SwRedlineAcceptDlg, RejectAllHdl));
pTPView->SetUndoClickHdl(LINK(this, SwRedlineAcceptDlg, UndoHdl));
aTabPagesCTRL.GetFilterPage()->SetReadyHdl(LINK(this, SwRedlineAcceptDlg, FilterChangedHdl));
ListBox *pActLB = aTabPagesCTRL.GetFilterPage()->GetLbAction();
pActLB->InsertEntry(sInserted);
pActLB->InsertEntry(sDeleted);
pActLB->InsertEntry(sFormated);
pActLB->InsertEntry(sTableChgd);
if (HasRedlineAutoFmt())
{
pActLB->InsertEntry(sFmtCollSet);
pActLB->InsertEntry(sAutoFormat);
pTPView->ShowUndo(sal_True);
pTPView->DisableUndo(); // Noch gibts keine UNDO-Events
}
pActLB->SelectEntryPos(0);
pTable->SetStyle(pTable->GetStyle()|WB_HASLINES|WB_CLIPCHILDREN|WB_HASBUTTONS|WB_HASBUTTONSATROOT|WB_HSCROLL);
pTable->SetNodeDefaultImages();
pTable->SetSelectionMode(MULTIPLE_SELECTION);
pTable->SetHighlightRange(1);
static long aStaticTabs[]=
{
4,10,70,120,170
};
pTable->SetTabs(aStaticTabs);
// Minimalgroesse setzen
Size aMinSz(aTabPagesCTRL.GetMinSizePixel());
Point aPos(aTabPagesCTRL.GetPosPixel());
aMinSz.Width() += (aPos.X() * 2 - 1);
aMinSz.Height() += (aPos.Y() * 2 - 1);
pParentDlg->SetMinOutputSizePixel(aMinSz);
if (pParentDlg->GetOutputSizePixel().Width() < aMinSz.Width())
pParentDlg->SetOutputSizePixel(Size(aMinSz.Width(), pParentDlg->GetOutputSizePixel().Height()));
if (pParentDlg->GetOutputSizePixel().Height() < aMinSz.Height())
pParentDlg->SetOutputSizePixel(Size(pParentDlg->GetOutputSizePixel().Width(), aMinSz.Height()));
pTable->SortByCol(nSortMode, bSortDir);
aOldSelectHdl = pTable->GetSelectHdl();
aOldDeselectHdl = pTable->GetDeselectHdl();
pTable->SetSelectHdl(LINK(this, SwRedlineAcceptDlg, SelectHdl));
pTable->SetDeselectHdl(LINK(this, SwRedlineAcceptDlg, DeselectHdl));
pTable->SetCommandHdl(LINK(this, SwRedlineAcceptDlg, CommandHdl));
// Flackern der Buttons vermeiden:
aDeselectTimer.SetTimeout(100);
aDeselectTimer.SetTimeoutHdl(LINK(this, SwRedlineAcceptDlg, SelectHdl));
// Mehrfachselektion der selben Texte vermeiden:
aSelectTimer.SetTimeout(100);
aSelectTimer.SetTimeoutHdl(LINK(this, SwRedlineAcceptDlg, GotoHdl));
}
/*------------------------------------------------------------------------
Beschreibung:
------------------------------------------------------------------------*/
SwRedlineAcceptDlg::~SwRedlineAcceptDlg()
{
}
/*------------------------------------------------------------------------
Beschreibung:
------------------------------------------------------------------------*/
void SwRedlineAcceptDlg::Init(sal_uInt16 nStart)
{
SwWait aWait( *::GetActiveView()->GetDocShell(), false );
pTable->SetUpdateMode(sal_False);
aUsedSeqNo.Remove((sal_uInt16)0, aUsedSeqNo.Count());
if (nStart)
RemoveParents(nStart, aRedlineParents.Count() - 1);
else
{
pTable->Clear();
aRedlineChilds.DeleteAndDestroy(0, aRedlineChilds.Count());
aRedlineParents.DeleteAndDestroy(nStart, aRedlineParents.Count() - nStart);
}
// Parents einfuegen
InsertParents(nStart);
InitAuthors();
pTable->SetUpdateMode(sal_True);
// #i69618# this moves the list box to the right position, visually
SvLBoxEntry* pSelEntry = pTable->FirstSelected();
if( pSelEntry )
pTable->MakeVisible( pSelEntry, sal_True ); //#i70937#, force the scroll
}
/*------------------------------------------------------------------------
Beschreibung:
------------------------------------------------------------------------*/
void SwRedlineAcceptDlg::InitAuthors()
{
SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr();
SvxTPFilter *pFilterPage = aTabPagesCTRL.GetFilterPage();
String sAuthor;
SvStringsSortDtor aStrings;
String sOldAuthor(pFilterPage->GetSelectedAuthor());
pFilterPage->ClearAuthors();
String sParent;
const sal_uInt16 nRedlineCount = pSh->GetRedlineCount();
bOnlyFormatedRedlines = sal_True;
bHasReadonlySel = sal_False;
sal_Bool bIsNotFormated = sal_False;
sal_uInt16 i;
// Autoren ermitteln
for ( i = 0; i < nRedlineCount; i++)
{
const SwRedline& rRedln = pSh->GetRedline(i);
if( bOnlyFormatedRedlines && nsRedlineType_t::REDLINE_FORMAT != rRedln.GetType() )
bOnlyFormatedRedlines = sal_False;
//JP 27.9.2001: make no sense if we handle readonly sections
// if( !bHasReadonlySel && rRedln.HasReadonlySel() )
// bHasReadonlySel = sal_True;
String *pAuthor = new String(rRedln.GetAuthorString());
if (!aStrings.Insert(pAuthor))
delete pAuthor;
for (sal_uInt16 nStack = 1; nStack < rRedln.GetStackCount(); nStack++)
{
pAuthor = new String(rRedln.GetAuthorString(nStack));
if (!aStrings.Insert(pAuthor))
delete pAuthor;
}
}
for (i = 0; i < aStrings.Count(); i++)
pFilterPage->InsertAuthor(*aStrings[i]);
if (pFilterPage->SelectAuthor(sOldAuthor) == LISTBOX_ENTRY_NOTFOUND && aStrings.Count())
pFilterPage->SelectAuthor(*aStrings[0]);
sal_Bool bEnable = pTable->GetEntryCount() != 0 && !pSh->getIDocumentRedlineAccess()->GetRedlinePassword().getLength();
sal_Bool bSel = pTable->FirstSelected() != 0;
{
SvLBoxEntry* pSelEntry = pTable->FirstSelected();
while (pSelEntry)
{
const sal_uInt16 nPos = GetRedlinePos(*pSelEntry);
if ( nPos < nRedlineCount )
{
const SwRedline& rRedln = pSh->GetRedline( nPos );
bIsNotFormated |= nsRedlineType_t::REDLINE_FORMAT != rRedln.GetType();
}
pSelEntry = pTable->NextSelected(pSelEntry);
}
}
pTPView->EnableAccept( bEnable && bSel );
pTPView->EnableReject( bEnable && bIsNotFormated && bSel );
pTPView->EnableAcceptAll( bEnable && !bHasReadonlySel );
pTPView->EnableRejectAll( bEnable && !bHasReadonlySel &&
!bOnlyFormatedRedlines );
}
/*------------------------------------------------------------------------
Beschreibung:
------------------------------------------------------------------------*/
String SwRedlineAcceptDlg::GetRedlineText( const SwRedline& rRedln,
DateTime &rDateTime, sal_uInt16 nStack)
{
String sEntry(GetActionText(rRedln, nStack));
sEntry += '\t';
sEntry += rRedln.GetAuthorString(nStack);
sEntry += '\t';
const DateTime &rDT = rRedln.GetTimeStamp(nStack);
rDateTime = rDT;
sEntry += GetAppLangDateTimeString( rDT );
sEntry += '\t';
sEntry += rRedln.GetComment(nStack);
return sEntry;
}
/*------------------------------------------------------------------------
Beschreibung:
------------------------------------------------------------------------*/
const String &SwRedlineAcceptDlg::GetActionText(const SwRedline& rRedln, sal_uInt16 nStack)
{
switch( rRedln.GetType(nStack) )
{
case nsRedlineType_t::REDLINE_INSERT: return sInserted;
case nsRedlineType_t::REDLINE_DELETE: return sDeleted;
case nsRedlineType_t::REDLINE_FORMAT: return sFormated;
case nsRedlineType_t::REDLINE_TABLE: return sTableChgd;
case nsRedlineType_t::REDLINE_FMTCOLL: return sFmtCollSet;
default:;//prevent warning
}
return aEmptyStr;
}
/*------------------------------------------------------------------------
Beschreibung:
------------------------------------------------------------------------*/
void SwRedlineAcceptDlg::Resize()
{
Size aSz(pParentDlg->GetOutputSizePixel());
Point aPos(aTabPagesCTRL.GetPosPixel());
aSz.Width() -= (aPos.X() * 2 - 1);
aSz.Height() -= (aPos.Y() * 2 - 1);
aTabPagesCTRL.SetOutputSizePixel(aSz);
}
/*--------------------------------------------------------------------
Beschreibung: Nach Aktivierung neu initialisieren
--------------------------------------------------------------------*/
void SwRedlineAcceptDlg::Activate()
{
// prevent update if flag is set (#102547#)
if( bInhibitActivate )
return;
SwView *pView = ::GetActiveView();
SwWait aWait( *pView->GetDocShell(), false );
aUsedSeqNo.Remove((sal_uInt16)0, aUsedSeqNo.Count());
if (!pView) // Kann passieren, wenn man auf eine andere App umschaltet, wenn
return; // vorher eine Listbox im Dialog den Focus hatte (eigentlich THs Bug)
/* if (HasRedlineAutoFmt())
{
Init();
return;
}*/
// Hat sich was geaendert?
SwWrtShell* pSh = pView->GetWrtShellPtr();
sal_uInt16 nCount = pSh->GetRedlineCount();
// Anzahl und Pointer ueberpruefen
SwRedlineDataParent *pParent = 0;
sal_uInt16 i;
for ( i = 0; i < nCount; i++)
{
const SwRedline& rRedln = pSh->GetRedline(i);
if (i >= aRedlineParents.Count())
{
// Neue Eintraege wurden angehaengt
Init(i);
return;
}
pParent = aRedlineParents[i];
if (&rRedln.GetRedlineData() != pParent->pData)
{
// Redline-Parents wurden eingefuegt, geaendert oder geloescht
if ((i = CalcDiff(i, sal_False)) == USHRT_MAX)
return;
continue;
}
const SwRedlineData *pRedlineData = rRedln.GetRedlineData().Next();
const SwRedlineDataChild *pBackupData = pParent->pNext;
if (!pRedlineData && pBackupData)
{
// Redline-Childs wurden geloescht
if ((i = CalcDiff(i, sal_True)) == USHRT_MAX)
return;
continue;
}
else
{
while (pRedlineData)
{
if (pRedlineData != pBackupData->pChild)
{
// Redline-Childs wurden eingefuegt, geaendert oder geloescht
if ((i = CalcDiff(i, sal_True)) == USHRT_MAX)
return;
continue;
}
if (pBackupData)
pBackupData = pBackupData->pNext;
pRedlineData = pRedlineData->Next();
}
}
}
if (nCount != aRedlineParents.Count())
{
// Redlines wurden am Ende geloescht
Init(nCount);
return;
}
// Kommentar ueberpruefen
for (i = 0; i < nCount; i++)
{
const SwRedline& rRedln = pSh->GetRedline(i);
pParent = aRedlineParents[i];
if(!rRedln.GetComment().Equals(pParent->sComment))
{
if (pParent->pTLBParent)
{
// Nur Kommentar aktualisieren
String sComment(rRedln.GetComment());
sComment.SearchAndReplaceAll((sal_Unicode)_LF,(sal_Unicode)' ');
pTable->SetEntryText(sComment, pParent->pTLBParent, 3);
}
pParent->sComment = rRedln.GetComment();
}
}
InitAuthors();
}
/* -----------------05.06.98 13:06-------------------
*
* --------------------------------------------------*/
sal_uInt16 SwRedlineAcceptDlg::CalcDiff(sal_uInt16 nStart, sal_Bool bChild)
{
if (!nStart)
{
Init();
return USHRT_MAX;
}
pTable->SetUpdateMode(sal_False);
SwView *pView = ::GetActiveView();
SwWrtShell* pSh = pView->GetWrtShellPtr();
sal_uInt16 nAutoFmt = HasRedlineAutoFmt() ? nsRedlineType_t::REDLINE_FORM_AUTOFMT : 0;
SwRedlineDataParent *pParent = aRedlineParents[nStart];
const SwRedline& rRedln = pSh->GetRedline(nStart);
if (bChild) // Sollte eigentlich nie vorkommen, aber sicher ist sicher...
{
// Alle Childs des Eintrags wegwerfen und neu initialisieren
SwRedlineDataChildPtr pBackupData = (SwRedlineDataChildPtr)pParent->pNext;
SwRedlineDataChildPtr pNext;
while (pBackupData)
{
pNext = (SwRedlineDataChildPtr)pBackupData->pNext;
if (pBackupData->pTLBChild)
pTable->RemoveEntry(pBackupData->pTLBChild);
aRedlineChilds.DeleteAndDestroy(aRedlineChilds.GetPos(pBackupData), 1);
pBackupData = pNext;
}
pParent->pNext = 0;
// Neue Childs einfuegen
InsertChilds(pParent, rRedln, nAutoFmt);
pTable->SetUpdateMode(sal_True);
return nStart;
}
// Wurden Eintraege geloescht?
const SwRedlineData *pRedlineData = &rRedln.GetRedlineData();
sal_uInt16 i;
for ( i = nStart + 1; i < aRedlineParents.Count(); i++)
{
if (aRedlineParents[i]->pData == pRedlineData)
{
// Eintraege von nStart bis i-1 entfernen
RemoveParents(nStart, i - 1);
pTable->SetUpdateMode(sal_True);
return nStart - 1;
}
}
// Wurden Eintraege eingefuegt?
sal_uInt16 nCount = pSh->GetRedlineCount();
pRedlineData = aRedlineParents[nStart]->pData;
for (i = nStart + 1; i < nCount; i++)
{
if (&pSh->GetRedline(i).GetRedlineData() == pRedlineData)
{
// Eintraege von nStart bis i-1 einfuegen
InsertParents(nStart, i - 1);
pTable->SetUpdateMode(sal_True);
return nStart - 1;
}
}
pTable->SetUpdateMode(sal_True);
Init(nStart); // Alle Eintraege bis zum Ende abgleichen
return USHRT_MAX;
}
/* -----------------05.06.98 13:57-------------------
*
* --------------------------------------------------*/
void SwRedlineAcceptDlg::InsertChilds(SwRedlineDataParent *pParent, const SwRedline& rRedln, const sal_uInt16 nAutoFmt)
{
String sChild;
SwRedlineDataChild *pLastRedlineChild = 0;
const SwRedlineData *pRedlineData = &rRedln.GetRedlineData();
sal_Bool bAutoFmt = (rRedln.GetRealType() & nAutoFmt) != 0;
const String *pAction = &GetActionText(rRedln);
sal_Bool bValidParent = !sFilterAction.Len() || sFilterAction == *pAction;
bValidParent = bValidParent && pTable->IsValidEntry(&rRedln.GetAuthorString(), &rRedln.GetTimeStamp(), &rRedln.GetComment());
if (nAutoFmt)
{
sal_uInt16 nPos;
if (pParent->pData->GetSeqNo() && !aUsedSeqNo.Insert(pParent, nPos)) // Gibts schon
{
if (pParent->pTLBParent)
{
pTable->SetEntryText(sAutoFormat, aUsedSeqNo[nPos]->pTLBParent, 0);
pTable->RemoveEntry(pParent->pTLBParent);
pParent->pTLBParent = 0;
}
return;
}
bValidParent = bValidParent && bAutoFmt;
}
sal_Bool bValidTree = bValidParent;
for (sal_uInt16 nStack = 1; nStack < rRedln.GetStackCount(); nStack++)
{
pRedlineData = pRedlineData->Next();
SwRedlineDataChildPtr pRedlineChild = new SwRedlineDataChild;
pRedlineChild->pChild = pRedlineData;
aRedlineChilds.Insert(pRedlineChild, aRedlineChilds.Count());
if ( pLastRedlineChild )
pLastRedlineChild->pNext = pRedlineChild;
else
pParent->pNext = pRedlineChild;
pAction = &GetActionText(rRedln, nStack);
sal_Bool bValidChild = !sFilterAction.Len() || sFilterAction == *pAction;
bValidChild = bValidChild && pTable->IsValidEntry(&rRedln.GetAuthorString(nStack), &rRedln.GetTimeStamp(nStack), &rRedln.GetComment());
if (nAutoFmt)
bValidChild = bValidChild && bAutoFmt;
bValidTree |= bValidChild;
if (bValidChild)
{
RedlinData *pData = new RedlinData;
pData->pData = pRedlineChild;
pData->bDisabled = sal_True;
sChild = GetRedlineText(rRedln, pData->aDateTime, nStack);
SvLBoxEntry* pChild = pTable->InsertEntry(sChild, pData, pParent->pTLBParent);
pRedlineChild->pTLBChild = pChild;
if (!bValidParent)
pTable->Expand(pParent->pTLBParent);
}
else
pRedlineChild->pTLBChild = 0;
pLastRedlineChild = pRedlineChild;
}
if (pLastRedlineChild)
pLastRedlineChild->pNext = 0;
if (!bValidTree && pParent->pTLBParent)
{
pTable->RemoveEntry(pParent->pTLBParent);
pParent->pTLBParent = 0;
if (nAutoFmt)
aUsedSeqNo.Remove(pParent);
}
}
/* -----------------05.06.98 15:20-------------------
*
* --------------------------------------------------*/
void SwRedlineAcceptDlg::RemoveParents(sal_uInt16 nStart, sal_uInt16 nEnd)
{
SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr();
sal_uInt16 nCount = pSh->GetRedlineCount();
SvLBoxEntryArr aLBoxArr;
// Wegen Bug der TLB, die bei Remove den SelectHandler IMMER ruft:
pTable->SetSelectHdl(aOldSelectHdl);
pTable->SetDeselectHdl(aOldDeselectHdl);
sal_Bool bChildsRemoved = sal_False;
pTable->SelectAll(sal_False);
// Hinter dem letzten Eintrag Cursor setzen, da sonst Performance-Problem in TLB.
// TLB wuerde sonst bei jedem Remove den Cursor erneut umsetzen (teuer)
sal_uInt16 nPos = Min((sal_uInt16)nCount, (sal_uInt16)aRedlineParents.Count());
SvLBoxEntry *pCurEntry = NULL;
while( ( pCurEntry == NULL ) && ( nPos > 0 ) )
{
--nPos;
pCurEntry = aRedlineParents[nPos]->pTLBParent;
}
if (pCurEntry)
pTable->SetCurEntry(pCurEntry);
SvLBoxTreeList* pModel = pTable->GetModel();
for (sal_uInt16 i = nStart; i <= nEnd; i++)
{
if (!bChildsRemoved && aRedlineParents[i]->pNext)
{
SwRedlineDataChildPtr pChildPtr = (SwRedlineDataChildPtr)aRedlineParents[i]->pNext;
sal_uInt16 nChildPos = aRedlineChilds.GetPos(pChildPtr);
if (nChildPos != USHRT_MAX)
{
sal_uInt16 nChilds = 0;
while (pChildPtr)
{
pChildPtr = (SwRedlineDataChildPtr)pChildPtr->pNext;
nChilds++;
}
aRedlineChilds.DeleteAndDestroy(nChildPos, nChilds);
bChildsRemoved = sal_True;
}
}
SvLBoxEntry *pEntry = aRedlineParents[i]->pTLBParent;
if (pEntry)
{
long nIdx = aLBoxArr.Count() - 1L;
sal_uLong nAbsPos = pModel->GetAbsPos(pEntry);
while (nIdx >= 0 &&
pModel->GetAbsPos(aLBoxArr[ static_cast< sal_uInt16 >(nIdx) ]) > nAbsPos)
nIdx--;
aLBoxArr.Insert( pEntry, static_cast< sal_uInt16 >(++nIdx) );
}
}
// TLB von hinten abraeumen
long nIdx = (long)aLBoxArr.Count() - 1L;
while (nIdx >= 0)
pTable->RemoveEntry(aLBoxArr[ static_cast< sal_uInt16 >(nIdx--) ]);
pTable->SetSelectHdl(LINK(this, SwRedlineAcceptDlg, SelectHdl));
pTable->SetDeselectHdl(LINK(this, SwRedlineAcceptDlg, DeselectHdl));
// Durch Remove wurde leider wieder dauernd von der TLB selektiert...
pTable->SelectAll(sal_False);
aRedlineParents.DeleteAndDestroy( nStart, nEnd - nStart + 1);
}
/* -----------------05.06.98 15:20-------------------
*
* --------------------------------------------------*/
void SwRedlineAcceptDlg::InsertParents(sal_uInt16 nStart, sal_uInt16 nEnd)
{
SwView *pView = ::GetActiveView();
SwWrtShell* pSh = pView->GetWrtShellPtr();
sal_uInt16 nAutoFmt = HasRedlineAutoFmt() ? nsRedlineType_t::REDLINE_FORM_AUTOFMT : 0;
String sParent;
const sal_uInt16 nCount = pSh->GetRedlineCount();
nEnd = Min((sal_uInt16)nEnd, (sal_uInt16)(nCount - 1)); // Handelt auch nEnd=USHRT_MAX (bis zum Ende) ab
if (nEnd == USHRT_MAX)
return; // Keine Redlines im Dokument
RedlinData *pData;
SvLBoxEntry *pParent;
SwRedlineDataParentPtr pRedlineParent;
const SwRedline* pCurrRedline;
if( !nStart && !pTable->FirstSelected() )
{
pCurrRedline = pSh->GetCurrRedline();
if( !pCurrRedline )
{
pSh->SwCrsrShell::Push();
if( 0 == (pCurrRedline = pSh->SelNextRedline()))
pCurrRedline = pSh->SelPrevRedline();
pSh->SwCrsrShell::Pop( sal_False );
}
}
else
pCurrRedline = 0;
for (sal_uInt16 i = nStart; i <= nEnd; i++)
{
const SwRedline& rRedln = pSh->GetRedline(i);
const SwRedlineData *pRedlineData = &rRedln.GetRedlineData();
pRedlineParent = new SwRedlineDataParent;
pRedlineParent->pData = pRedlineData;
pRedlineParent->pNext = 0;
String sComment(rRedln.GetComment());
sComment.SearchAndReplaceAll((sal_Unicode)_LF,(sal_Unicode)' ');
pRedlineParent->sComment = sComment;
aRedlineParents.Insert(pRedlineParent, i);
pData = new RedlinData;
pData->pData = pRedlineParent;
pData->bDisabled = sal_False;
sParent = GetRedlineText(rRedln, pData->aDateTime);
pParent = pTable->InsertEntry(sParent, pData, 0, i);
if( pCurrRedline == &rRedln )
{
pTable->SetCurEntry( pParent );
pTable->Select( pParent );
pTable->MakeVisible( pParent );
}
pRedlineParent->pTLBParent = pParent;
InsertChilds(pRedlineParent, rRedln, nAutoFmt);
}
}
/* -----------------05.06.98 13:06-------------------
*
* --------------------------------------------------*/
void SwRedlineAcceptDlg::CallAcceptReject( sal_Bool bSelect, sal_Bool bAccept )
{
SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr();
SvLBoxEntry* pEntry = bSelect ? pTable->FirstSelected() : pTable->First();
sal_uLong nPos = LONG_MAX;
typedef std::vector<SvLBoxEntry*> ListBoxEntries_t;
ListBoxEntries_t aRedlines;
// don't activate
DBG_ASSERT( bInhibitActivate == false,
"recursive call of CallAcceptReject?");
bInhibitActivate = true;
// collect redlines-to-be-accepted/rejected in aRedlines vector
while( pEntry )
{
if( !pTable->GetParent( pEntry ) )
{
if( bSelect && LONG_MAX == nPos )
nPos = pTable->GetModel()->GetAbsPos( pEntry );
RedlinData *pData = (RedlinData *)pEntry->GetUserData();
if( !pData->bDisabled )
aRedlines.push_back( pEntry );
}
pEntry = bSelect ? pTable->NextSelected(pEntry) : pTable->Next(pEntry);
}
sal_Bool (SwEditShell:: *FnAccRej)( sal_uInt16 ) = &SwEditShell::AcceptRedline;
if( !bAccept )
FnAccRej = &SwEditShell::RejectRedline;
SwWait aWait( *pSh->GetView().GetDocShell(), true );
pSh->StartAction();
// #111827#
if (aRedlines.size() > 1)
{
String aTmpStr;
{
SwRewriter aRewriter;
aRewriter.AddRule(UNDO_ARG1,
String::CreateFromInt32(aRedlines.size()));
aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES)));
}
SwRewriter aRewriter;
aRewriter.AddRule(UNDO_ARG1, aTmpStr);
pSh->StartUndo(bAccept? UNDO_ACCEPT_REDLINE : UNDO_REJECT_REDLINE,
&aRewriter);
}
// accept/reject the the redlines in aRedlines. The absolute
// position may change during the process (e.g. when two redlines
// are merged in result of another one being deleted), so the
// position must be resolved late and checked before using it.
// (cf #102547#)
ListBoxEntries_t::iterator aEnd = aRedlines.end();
for( ListBoxEntries_t::iterator aIter = aRedlines.begin();
aIter != aEnd;
aIter++ )
{
const sal_uInt16 nPosition = GetRedlinePos( **aIter );
if( nPosition != USHRT_MAX )
(pSh->*FnAccRej)( nPosition );
}
// #111827#
if (aRedlines.size() > 1)
{
pSh->EndUndo();
}
pSh->EndAction();
bInhibitActivate = false;
Activate();
if( ULONG_MAX != nPos && pTable->GetEntryCount() )
{
if( nPos >= pTable->GetEntryCount() )
nPos = pTable->GetEntryCount() - 1;
pEntry = pTable->GetEntry( nPos );
if( !pEntry && nPos-- )
pEntry = pTable->GetEntry( nPos );
if( pEntry )
{
pTable->Select( pEntry );
pTable->MakeVisible( pEntry );
pTable->SetCurEntry(pEntry);
}
}
pTPView->EnableUndo();
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
sal_uInt16 SwRedlineAcceptDlg::GetRedlinePos( const SvLBoxEntry& rEntry ) const
{
SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr();
return pSh->FindRedlineOfData( *((SwRedlineDataParent*)((RedlinData *)
rEntry.GetUserData())->pData)->pData );
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
IMPL_LINK( SwRedlineAcceptDlg, AcceptHdl, void*, EMPTYARG)
{
CallAcceptReject( sal_True, sal_True );
return 0;
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
IMPL_LINK( SwRedlineAcceptDlg, AcceptAllHdl, void*, EMPTYARG )
{
CallAcceptReject( sal_False, sal_True );
return 0;
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
IMPL_LINK( SwRedlineAcceptDlg, RejectHdl, void*, EMPTYARG )
{
CallAcceptReject( sal_True, sal_False );
return 0;
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
IMPL_LINK( SwRedlineAcceptDlg, RejectAllHdl, void*, EMPTYARG )
{
CallAcceptReject( sal_False, sal_False );
return 0;
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
IMPL_LINK( SwRedlineAcceptDlg, UndoHdl, void*, EMPTYARG )
{
SwView * pView = ::GetActiveView();
pView->GetViewFrame()->GetDispatcher()->
Execute(SID_UNDO, SFX_CALLMODE_SYNCHRON);
pTPView->EnableUndo(pView->GetSlotState(SID_UNDO) != 0);
Activate();
return 0;
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
IMPL_LINK( SwRedlineAcceptDlg, FilterChangedHdl, void*, EMPTYARG )
{
SvxTPFilter *pFilterTP = aTabPagesCTRL.GetFilterPage();
if (pFilterTP->IsAction())
sFilterAction = pFilterTP->GetLbAction()->GetSelectEntry();
else
sFilterAction = aEmptyStr;
Init();
return 0;
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
IMPL_LINK( SwRedlineAcceptDlg, DeselectHdl, void*, EMPTYARG )
{
// Flackern der Buttons vermeiden:
aDeselectTimer.Start();
return 0;
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
IMPL_LINK( SwRedlineAcceptDlg, SelectHdl, void*, EMPTYARG )
{
aDeselectTimer.Stop();
aSelectTimer.Start();
return 0;
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
IMPL_LINK( SwRedlineAcceptDlg, GotoHdl, void*, EMPTYARG )
{
SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr();
aSelectTimer.Stop();
sal_Bool bIsNotFormated = sal_False;
sal_Bool bSel = sal_False;
//#98883# don't select redlines while the dialog is not focussed
//#107938# But not only ask pTable if it has the focus. To move
// the selection to the selected redline any child of pParentDlg
// may the focus.
SvLBoxEntry* pSelEntry = 0;
if (pParentDlg->HasChildPathFocus())
pSelEntry = pTable->FirstSelected();
if( pSelEntry )
{
SvLBoxEntry* pActEntry = pSelEntry;
pSh->StartAction();
pSh->EnterStdMode();
pSh->SetCareWin(pParentDlg);
while (pSelEntry)
{
if (pTable->GetParent(pSelEntry))
{
pActEntry = pTable->GetParent(pSelEntry);
if (pTable->IsSelected(pActEntry))
{
pSelEntry = pActEntry = pTable->NextSelected(pSelEntry);
continue; // Nicht zweimal selektieren
}
}
else
bSel = sal_True;
// #98864# find the selected redline (ignore, if the redline is already gone)
const sal_uInt16 nPos = GetRedlinePos(*pActEntry);
if ( nPos < pSh->GetRedlineCount() )
{
const SwRedline& rRedln = pSh->GetRedline( nPos );
bIsNotFormated |= nsRedlineType_t::REDLINE_FORMAT != rRedln.GetType();
if (pSh->GotoRedline(nPos, sal_True))
{
pSh->SetInSelect();
pSh->EnterAddMode();
}
}
pSelEntry = pActEntry = pTable->NextSelected(pSelEntry);
}
pSh->LeaveAddMode();
pSh->EndAction();
pSh->SetCareWin(NULL);
}
sal_Bool bEnable = !pSh->getIDocumentRedlineAccess()->GetRedlinePassword().getLength();
pTPView->EnableAccept( bEnable && bSel /*&& !bReadonlySel*/ );
pTPView->EnableReject( bEnable && bSel && bIsNotFormated /*&& !bReadonlySel*/ );
pTPView->EnableRejectAll( bEnable && !bOnlyFormatedRedlines && !bHasReadonlySel );
return 0;
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
IMPL_LINK( SwRedlineAcceptDlg, CommandHdl, void*, EMPTYARG )
{
const CommandEvent aCEvt(pTable->GetCommandEvent());
switch ( aCEvt.GetCommand() )
{
case COMMAND_CONTEXTMENU:
{
SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr();
SvLBoxEntry* pEntry = pTable->FirstSelected();
const SwRedline *pRed = 0;
if (pEntry)
{
SvLBoxEntry* pTopEntry = pEntry;
if (pTable->GetParent(pEntry))
pTopEntry = pTable->GetParent(pEntry);
const sal_uInt16 nPos = GetRedlinePos(*pTopEntry);
// Bei geschuetzten Bereichen kommentieren disablen
if ((pRed = pSh->GotoRedline(nPos, sal_True)) != 0)
{
if( pSh->IsCrsrPtAtEnd() )
pSh->SwapPam();
pSh->SetInSelect();
}
}
aPopup.EnableItem( MN_EDIT_COMMENT, pEntry && pRed &&
!pTable->GetParent(pEntry) &&
!pTable->NextSelected(pEntry)
//JP 27.9.2001: make no sense if we handle readonly sections
// && pRed->HasReadonlySel()
);
aPopup.EnableItem( MN_SUB_SORT, pTable->First() != 0 );
sal_uInt16 nColumn = pTable->GetSortedCol();
if (nColumn == 0xffff)
nColumn = 4;
PopupMenu *pSubMenu = aPopup.GetPopupMenu(MN_SUB_SORT);
if (pSubMenu)
{
for (sal_uInt16 i = MN_SORT_ACTION; i < MN_SORT_ACTION + 5; i++)
pSubMenu->CheckItem(i, sal_False);
pSubMenu->CheckItem(nColumn + MN_SORT_ACTION);
}
sal_uInt16 nRet = aPopup.Execute(pTable, aCEvt.GetMousePosPixel());
switch( nRet )
{
case MN_EDIT_COMMENT:
{
String sComment;
if (pEntry)
{
if (pTable->GetParent(pEntry))
pEntry = pTable->GetParent(pEntry);
const sal_uInt16 nPos = GetRedlinePos(*pEntry);
if ( nPos >= pSh->GetRedlineCount() )
{
break;
}
const SwRedline &rRedline = pSh->GetRedline(nPos);
/* enable again once we have redline comments in the margin
sComment = rRedline.GetComment();
if ( sComment == String(::rtl::OUString::createFromAscii("")) )
GetActiveView()->GetDocShell()->Broadcast(SwRedlineHint(&rRedline,SWREDLINE_INSERTED));
const_cast<SwRedline&>(rRedline).Broadcast(SwRedlineHint(&rRedline,SWREDLINE_FOCUS));
*/
sComment = rRedline.GetComment();
SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
DBG_ASSERT(pFact, "Dialogdiet fail!");
::DialogGetRanges fnGetRange = pFact->GetDialogGetRangesFunc( RID_SVXDLG_POSTIT );
DBG_ASSERT(fnGetRange, "Dialogdiet fail! GetRanges()");
SfxItemSet aSet( pSh->GetAttrPool(), fnGetRange() );
aSet.Put(SvxPostItTextItem(sComment.ConvertLineEnd(), SID_ATTR_POSTIT_TEXT));
aSet.Put(SvxPostItAuthorItem(rRedline.GetAuthorString(), SID_ATTR_POSTIT_AUTHOR));
aSet.Put(SvxPostItDateItem( GetAppLangDateTimeString(
rRedline.GetRedlineData().GetTimeStamp() ),
SID_ATTR_POSTIT_DATE ));
AbstractSvxPostItDialog* pDlg = pFact->CreateSvxPostItDialog( pParentDlg, aSet, sal_False );
DBG_ASSERT(pDlg, "Dialogdiet fail!");
pDlg->HideAuthor();
sal_uInt16 nResId = 0;
switch( rRedline.GetType() )
{
case nsRedlineType_t::REDLINE_INSERT:
nResId = STR_REDLINE_INSERTED;
break;
case nsRedlineType_t::REDLINE_DELETE:
nResId = STR_REDLINE_DELETED;
break;
case nsRedlineType_t::REDLINE_FORMAT:
nResId = STR_REDLINE_FORMATED;
break;
case nsRedlineType_t::REDLINE_TABLE:
nResId = STR_REDLINE_TABLECHG;
break;
default:;//prevent warning
}
String sTitle(SW_RES(STR_REDLINE_COMMENT));
if( nResId )
sTitle += SW_RESSTR( nResId );
pDlg->SetText(sTitle);
pSh->SetCareWin(pDlg->GetWindow());
if ( pDlg->Execute() == RET_OK )
{
const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
String sMsg(((const SvxPostItTextItem&)pOutSet->Get(SID_ATTR_POSTIT_TEXT)).GetValue());
// Kommentar einfuegen bzw aendern
pSh->SetRedlineComment(sMsg);
sMsg.SearchAndReplaceAll((sal_Unicode)_LF,(sal_Unicode)' ');
pTable->SetEntryText(sMsg, pEntry, 3);
}
delete pDlg;
pSh->SetCareWin(NULL);
}
}
break;
case MN_SORT_ACTION:
case MN_SORT_AUTHOR:
case MN_SORT_DATE:
case MN_SORT_COMMENT:
case MN_SORT_POSITION:
{
bSortDir = sal_True;
if (nRet - MN_SORT_ACTION == 4 && pTable->GetSortedCol() == 0xffff)
break; // Haben wir schon
nSortMode = nRet - MN_SORT_ACTION;
if (nSortMode == 4)
nSortMode = 0xffff; // unsortiert bzw sortiert nach Position
if (pTable->GetSortedCol() == nSortMode)
bSortDir = !pTable->GetSortDirection();
SwWait aWait( *::GetActiveView()->GetDocShell(), false );
pTable->SortByCol(nSortMode, bSortDir);
if (nSortMode == 0xffff)
Init(); // Alles neu fuellen
}
break;
}
}
break;
}
return 0;
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
void SwRedlineAcceptDlg::Initialize(const String& rExtraData)
{
if (rExtraData.Len())
{
sal_uInt16 nPos = rExtraData.Search(C2S("AcceptChgDat:"));
// Versuche, den Alignment-String "ALIGN:(...)" einzulesen; wenn
// er nicht vorhanden ist, liegt eine "altere Version vor
if (nPos != STRING_NOTFOUND)
{
sal_uInt16 n1 = rExtraData.Search('(', nPos);
if (n1 != STRING_NOTFOUND)
{
sal_uInt16 n2 = rExtraData.Search(')', n1);
if (n2 != STRING_NOTFOUND)
{
// Alignment-String herausschneiden
String aStr = rExtraData.Copy(nPos, n2 - nPos + 1);
aStr.Erase(0, n1 - nPos + 1);
if (aStr.Len())
{
sal_uInt16 nCount = static_cast< sal_uInt16 >(aStr.ToInt32());
for (sal_uInt16 i = 0; i < nCount; i++)
{
sal_uInt16 n3 = aStr.Search(';');
aStr.Erase(0, n3 + 1);
pTable->SetTab(i, aStr.ToInt32(), MAP_PIXEL);
}
}
}
}
}
}
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
void SwRedlineAcceptDlg::FillInfo(String &rExtraData) const
{
rExtraData.AppendAscii("AcceptChgDat:(");
sal_uInt16 nCount = pTable->TabCount();
rExtraData += String::CreateFromInt32(nCount);
rExtraData += ';';
for(sal_uInt16 i = 0; i < nCount; i++)
{
rExtraData += String::CreateFromInt32( pTable->GetTab(i) );
rExtraData += ';';
}
rExtraData += ')';
}