/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef _REDLNDLG_HXX #define _REDLNACCEPTDLG #include #endif #include #include #include #include #include #include #include // -> #111827# #include #include #include // <- #111827# #include #include #include #include #include #include SFX_IMPL_MODELESSDIALOG( SwRedlineAcceptChild, FN_REDLINE_ACCEPT ) SV_IMPL_OP_PTRARR_SORT(SwRedlineDataParentSortArr, SwRedlineDataParentPtr) static sal_uInt16 nSortMode = 0xffff; static sal_Bool bSortDir = sal_True; SwRedlineAcceptChild::SwRedlineAcceptChild( Window* _pParent, sal_uInt16 nId, SfxBindings* pBindings, SfxChildWinInfo* pInfo ) : SwChildWinWrapper( _pParent, nId ) { pWindow = new SwModelessRedlineAcceptDlg( pBindings, this, _pParent); ((SwModelessRedlineAcceptDlg *)pWindow)->Initialize(pInfo); } /*-------------------------------------------------------------------- Description: newly initialise dialog after document switch --------------------------------------------------------------------*/ sal_Bool SwRedlineAcceptChild::ReInitDlg(SwDocShell *pDocSh) { sal_Bool bRet; if ((bRet = SwChildWinWrapper::ReInitDlg(pDocSh)) == sal_True) // update immediately, doc switch! ((SwModelessRedlineAcceptDlg*)GetWindow())->Activate(); return bRet; } SwModelessRedlineAcceptDlg::SwModelessRedlineAcceptDlg( SfxBindings* _pBindings, SwChildWinWrapper* pChild, Window *_pParent) : SfxModelessDialog(_pBindings, pChild, _pParent, SW_RES(DLG_REDLINE_ACCEPT)), pChildWin (pChild) { pImplDlg = new SwRedlineAcceptDlg(this); FreeResource(); } void SwModelessRedlineAcceptDlg::Activate() { SwView *pView = ::GetActiveView(); if (!pView) // can happen when switching to another app, when a Listbox in dialog return; // had the focus previously (actually THs Bug) SwDocShell *pDocSh = pView->GetDocShell(); if (pChildWin->GetOldDocShell() != pDocSh) { // doc-switch SwWait aWait( *pDocSh, sal_False ); SwWrtShell* pSh = pView->GetWrtShellPtr(); pChildWin->SetOldDocShell(pDocSh); // avoid recursion (using 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(); } void SwModelessRedlineAcceptDlg::Initialize(SfxChildWinInfo *pInfo) { String aStr; if (pInfo != NULL) pImplDlg->Initialize(pInfo->aExtraString); SfxModelessDialog::Initialize(pInfo); } void SwModelessRedlineAcceptDlg::FillInfo(SfxChildWinInfo& rInfo) const { SfxModelessDialog::FillInfo(rInfo); pImplDlg->FillInfo(rInfo.aExtraString); } void SwModelessRedlineAcceptDlg::Resize() { pImplDlg->Resize(); SfxModelessDialog::Resize(); } SwModelessRedlineAcceptDlg::~SwModelessRedlineAcceptDlg() { delete pImplDlg; } 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(); // no UNDO events yet } 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); // set minimum size 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)); // avoid flickering of buttons: aDeselectTimer.SetTimeout(100); aDeselectTimer.SetTimeoutHdl(LINK(this, SwRedlineAcceptDlg, SelectHdl)); // avoid multiple selection of the same texts: aSelectTimer.SetTimeout(100); aSelectTimer.SetTimeoutHdl(LINK(this, SwRedlineAcceptDlg, GotoHdl)); } SwRedlineAcceptDlg::~SwRedlineAcceptDlg() { } void SwRedlineAcceptDlg::Init(sal_uInt16 nStart) { SwWait aWait( *::GetActiveView()->GetDocShell(), sal_False ); pTable->SetUpdateMode(sal_False); aUsedSeqNo.Remove((sal_uInt16)0, aUsedSeqNo.Count()); if (nStart) RemoveParents(nStart, aRedlineParents.size() - 1); else { pTable->Clear(); aRedlineChildren.clear(); aRedlineParents.erase(aRedlineParents.begin() + nStart, aRedlineParents.end()); } // insert parents 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 } void SwRedlineAcceptDlg::InitAuthors() { SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr(); SvxTPFilter *pFilterPage = aTabPagesCTRL.GetFilterPage(); String sAuthor; std::vector aStrings; String sOldAuthor(pFilterPage->GetSelectedAuthor()); pFilterPage->ClearAuthors(); String sParent; sal_uInt16 nCount = pSh->GetRedlineCount(); bOnlyFormatedRedlines = sal_True; bHasReadonlySel = sal_False; sal_Bool bIsNotFormated = sal_False; sal_uInt16 i; // determine authors for ( i = 0; i < nCount; i++) { const SwRedline& rRedln = pSh->GetRedline(i); if( bOnlyFormatedRedlines && nsRedlineType_t::REDLINE_FORMAT != rRedln.GetType() ) bOnlyFormatedRedlines = sal_False; aStrings.push_back(rRedln.GetAuthorString()); for (sal_uInt16 nStack = 1; nStack < rRedln.GetStackCount(); nStack++) { aStrings.push_back(rRedln.GetAuthorString(nStack)); } } std::sort(aStrings.begin(), aStrings.end()); aStrings.erase(std::unique(aStrings.begin(), aStrings.end()), aStrings.end()); for (i = 0; i < aStrings.size(); i++) pFilterPage->InsertAuthor(aStrings[i]); if (pFilterPage->SelectAuthor(sOldAuthor) == LISTBOX_ENTRY_NOTFOUND && !aStrings.empty()) 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) { sal_uInt16 nPos = GetRedlinePos(*pSelEntry); 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 ); } 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; } 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; } 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); } /*-------------------------------------------------------------------- Description: newly initialise after activation --------------------------------------------------------------------*/ void SwRedlineAcceptDlg::Activate() { // prevent update if flag is set (#102547#) if( bInhibitActivate ) return; SwView *pView = ::GetActiveView(); SwWait aWait( *pView->GetDocShell(), sal_False ); aUsedSeqNo.Remove((sal_uInt16)0, aUsedSeqNo.Count()); if (!pView) // can happen when switching to another app, when a Listbox in the dialog return; // had the focus previously (actually THs Bug) // did something change? SwWrtShell* pSh = pView->GetWrtShellPtr(); sal_uInt16 nCount = pSh->GetRedlineCount(); // check the number of pointers SwRedlineDataParent *pParent = 0; sal_uInt16 i; for ( i = 0; i < nCount; i++) { const SwRedline& rRedln = pSh->GetRedline(i); if (i >= aRedlineParents.size()) { // new entries have been appended Init(i); return; } pParent = &aRedlineParents[i]; if (&rRedln.GetRedlineData() != pParent->pData) { // Redline-Parents were inserted, changed or deleted 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-Children were deleted if ((i = CalcDiff(i, sal_True)) == USHRT_MAX) return; continue; } else { while (pRedlineData) { if (pRedlineData != pBackupData->pChild) { // Redline-Children were inserted, changed or deleted if ((i = CalcDiff(i, sal_True)) == USHRT_MAX) return; continue; } if (pBackupData) pBackupData = pBackupData->pNext; pRedlineData = pRedlineData->Next(); } } } if (nCount != aRedlineParents.size()) { // Redlines were deleted at the end Init(nCount); return; } // check comment for (i = 0; i < nCount; i++) { const SwRedline& rRedln = pSh->GetRedline(i); pParent = &aRedlineParents[i]; if(!rRedln.GetComment().Equals(pParent->sComment)) { if (pParent->pTLBParent) { // update only comment String sComment(rRedln.GetComment()); sComment.SearchAndReplaceAll((sal_Unicode)_LF,(sal_Unicode)' '); pTable->SetEntryText(sComment, pParent->pTLBParent, 3); } pParent->sComment = rRedln.GetComment(); } } InitAuthors(); } 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) // should actually never happen, but just in case... { // throw away all entry's children and initialise newly SwRedlineDataChild* pBackupData = (SwRedlineDataChild*)pParent->pNext; SwRedlineDataChild* pNext; while (pBackupData) { pNext = (SwRedlineDataChild*)pBackupData->pNext; if (pBackupData->pTLBChild) pTable->RemoveEntry(pBackupData->pTLBChild); for( SwRedlineDataChildArr::iterator it = aRedlineChildren.begin(); it != aRedlineChildren.end(); ++it) if (&*it == pBackupData) { aRedlineChildren.erase(it); break; } pBackupData = pNext; } pParent->pNext = 0; // insert new children InsertChildren(pParent, rRedln, nAutoFmt); pTable->SetUpdateMode(sal_True); return nStart; } // have entries been deleted? const SwRedlineData *pRedlineData = &rRedln.GetRedlineData(); sal_uInt16 i; for ( i = nStart + 1; i < aRedlineParents.size(); i++) { if (aRedlineParents[i].pData == pRedlineData) { // remove entries from nStart to i-1 RemoveParents(nStart, i - 1); pTable->SetUpdateMode(sal_True); return nStart - 1; } } // entries been inserted? sal_uInt16 nCount = pSh->GetRedlineCount(); pRedlineData = aRedlineParents[nStart].pData; for (i = nStart + 1; i < nCount; i++) { if (&pSh->GetRedline(i).GetRedlineData() == pRedlineData) { // insert entries from nStart to i-1 InsertParents(nStart, i - 1); pTable->SetUpdateMode(sal_True); return nStart - 1; } } pTable->SetUpdateMode(sal_True); Init(nStart); // adjust all entries until the end return USHRT_MAX; } void SwRedlineAcceptDlg::InsertChildren(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)) // already there { 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; aRedlineChildren.push_back(pRedlineChild); 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); } } void SwRedlineAcceptDlg::RemoveParents(sal_uInt16 nStart, sal_uInt16 nEnd) { SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr(); sal_uInt16 nCount = pSh->GetRedlineCount(); SvLBoxEntryArr aLBoxArr; // because of Bug of TLB that ALWAYS calls the SelectHandler at Remove: pTable->SetSelectHdl(aOldSelectHdl); pTable->SetDeselectHdl(aOldDeselectHdl); sal_Bool bChildrenRemoved = sal_False; pTable->SelectAll(sal_False); // set the cursor after the last entry because otherwise performance problem in TLB. // TLB would otherwise reset the cursor at every Remove (expensive) sal_uInt16 nPos = Min((sal_uInt16)nCount, (sal_uInt16)aRedlineParents.size()); 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 (!bChildrenRemoved && aRedlineParents[i].pNext) { SwRedlineDataChildPtr pChildPtr = (SwRedlineDataChildPtr)aRedlineParents[i].pNext; for( SwRedlineDataChildArr::iterator it = aRedlineChildren.begin(); it != aRedlineChildren.end(); ++it) if (&*it == pChildPtr) { sal_uInt16 nChildren = 0; while (pChildPtr) { pChildPtr = (SwRedlineDataChildPtr)pChildPtr->pNext; nChildren++; } aRedlineChildren.erase(it, it + nChildren); bChildrenRemoved = sal_True; break; } } SvLBoxEntry *pEntry = aRedlineParents[i].pTLBParent; if (pEntry) { long nIdx = aLBoxArr.size() - 1L; sal_uLong nAbsPos = pModel->GetAbsPos(pEntry); while (nIdx >= 0 && pModel->GetAbsPos(aLBoxArr[ static_cast< sal_uInt16 >(nIdx) ]) > nAbsPos) nIdx--; aLBoxArr.insert( aLBoxArr.begin() + static_cast< sal_uInt16 >(++nIdx) , pEntry); } } // clear TLB from behind long nIdx = (long)aLBoxArr.size() - 1L; while (nIdx >= 0) pTable->RemoveEntry(aLBoxArr[ static_cast< sal_uInt16 >(nIdx--) ]); pTable->SetSelectHdl(LINK(this, SwRedlineAcceptDlg, SelectHdl)); pTable->SetDeselectHdl(LINK(this, SwRedlineAcceptDlg, DeselectHdl)); // unfortunately by Remove it was selected from the TLB always again ... pTable->SelectAll(sal_False); aRedlineParents.erase( aRedlineParents.begin() + nStart, aRedlineParents.begin() + nEnd + 1); } 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; sal_uInt16 nCount = pSh->GetRedlineCount(); nEnd = Min((sal_uInt16)nEnd, (sal_uInt16)(nCount - 1)); // also treats nEnd=USHRT_MAX (until the end) if (nEnd == USHRT_MAX) return; // no redlines in the document 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(aRedlineParents.begin() + i, pRedlineParent); 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; InsertChildren(pRedlineParent, rRedln, nAutoFmt); } } 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 ListBoxEntries_t; ListBoxEntries_t aRedlines; // don't activate OSL_ENSURE( 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(), sal_True ); pSh->StartAction(); // #111827# if (aRedlines.size() > 1) { String aTmpStr; { SwRewriter aRewriter; aRewriter.AddRule(UndoArg1, String::CreateFromInt32(aRedlines.size())); aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES))); } SwRewriter aRewriter; aRewriter.AddRule(UndoArg1, 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++ ) { 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(); } sal_uInt16 SwRedlineAcceptDlg::GetRedlinePos( const SvLBoxEntry& rEntry ) const { SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr(); return pSh->FindRedlineOfData( *((SwRedlineDataParent*)((RedlinData *) rEntry.GetUserData())->pData)->pData ); } IMPL_LINK_NOARG(SwRedlineAcceptDlg, AcceptHdl) { CallAcceptReject( sal_True, sal_True ); return 0; } IMPL_LINK_NOARG(SwRedlineAcceptDlg, AcceptAllHdl) { CallAcceptReject( sal_False, sal_True ); return 0; } IMPL_LINK_NOARG(SwRedlineAcceptDlg, RejectHdl) { CallAcceptReject( sal_True, sal_False ); return 0; } IMPL_LINK_NOARG(SwRedlineAcceptDlg, RejectAllHdl) { CallAcceptReject( sal_False, sal_False ); return 0; } IMPL_LINK_NOARG(SwRedlineAcceptDlg, UndoHdl) { SwView * pView = ::GetActiveView(); pView->GetViewFrame()->GetDispatcher()-> Execute(SID_UNDO, SFX_CALLMODE_SYNCHRON); pTPView->EnableUndo(pView->GetSlotState(SID_UNDO) != 0); Activate(); return 0; } IMPL_LINK_NOARG(SwRedlineAcceptDlg, FilterChangedHdl) { SvxTPFilter *pFilterTP = aTabPagesCTRL.GetFilterPage(); if (pFilterTP->IsAction()) sFilterAction = pFilterTP->GetLbAction()->GetSelectEntry(); else sFilterAction = aEmptyStr; Init(); return 0; } IMPL_LINK_NOARG(SwRedlineAcceptDlg, DeselectHdl) { // avoid flickering of buttons: aDeselectTimer.Start(); return 0; } IMPL_LINK_NOARG(SwRedlineAcceptDlg, SelectHdl) { aDeselectTimer.Stop(); aSelectTimer.Start(); return 0; } IMPL_LINK_NOARG(SwRedlineAcceptDlg, GotoHdl) { 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; // don't select twice } } else bSel = sal_True; // #98864# find the selected redline (ignore, if the redline is already gone) sal_uInt16 nPos = GetRedlinePos(*pActEntry); if( nPos != USHRT_MAX ) { 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; } IMPL_LINK_NOARG(SwRedlineAcceptDlg, CommandHdl) { 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); sal_uInt16 nPos = GetRedlinePos(*pTopEntry); // disable commenting for protected areas 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: { if (pEntry) { if (pTable->GetParent(pEntry)) pEntry = pTable->GetParent(pEntry); sal_uInt16 nPos = GetRedlinePos(*pEntry); const SwRedline &rRedline = pSh->GetRedline(nPos); /* enable again once we have redline comments in the margin sComment = rRedline.GetComment(); if ( !sComment.Len() ) GetActiveView()->GetDocShell()->Broadcast(SwRedlineHint(&rRedline,SWREDLINE_INSERTED)); const_cast(rRedline).Broadcast(SwRedlineHint(&rRedline,SWREDLINE_FOCUS)); */ rtl::OUString sComment = convertLineEnd(rRedline.GetComment(), GetSystemLineEnd()); SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); OSL_ENSURE(pFact, "Dialogdiet fail!"); ::DialogGetRanges fnGetRange = pFact->GetDialogGetRangesFunc( RID_SVXDLG_POSTIT ); OSL_ENSURE(fnGetRange, "Dialogdiet fail! GetRanges()"); SfxItemSet aSet( pSh->GetAttrPool(), fnGetRange() ); aSet.Put(SvxPostItTextItem(sComment, 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 ); OSL_ENSURE(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()); // insert / change comment 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; // we already have it nSortMode = nRet - MN_SORT_ACTION; if (nSortMode == 4) nSortMode = 0xffff; // unsorted / sorted by position if (pTable->GetSortedCol() == nSortMode) bSortDir = !pTable->GetSortDirection(); SwWait aWait( *::GetActiveView()->GetDocShell(), sal_False ); pTable->SortByCol(nSortMode, bSortDir); if (nSortMode == 0xffff) Init(); // newly fill everything } break; } } break; } return 0; } void SwRedlineAcceptDlg::Initialize(const String& rExtraData) { if (rExtraData.Len()) { sal_uInt16 nPos = rExtraData.Search(C2S("AcceptChgDat:")); // try to read the alignment string "ALIGN:(...)"; if none existing, // it's an old version if (nPos != STRING_NOTFOUND) { sal_uInt16 n1 = rExtraData.Search('(', nPos); if (n1 != STRING_NOTFOUND) { sal_uInt16 n2 = rExtraData.Search(')', n1); if (n2 != STRING_NOTFOUND) { // cut out the alignment string 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); } } } } } } } 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 += ')'; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */