460 lines
15 KiB
C++
460 lines
15 KiB
C++
/*************************************************************************
|
|
*
|
|
* $RCSfile: arealink.cxx,v $
|
|
*
|
|
* $Revision: 1.5 $
|
|
*
|
|
* last change: $Author: sab $ $Date: 2001-02-14 15:31:48 $
|
|
*
|
|
* The Contents of this file are made available subject to the terms of
|
|
* either of the following licenses
|
|
*
|
|
* - GNU Lesser General Public License Version 2.1
|
|
* - Sun Industry Standards Source License Version 1.1
|
|
*
|
|
* Sun Microsystems Inc., October, 2000
|
|
*
|
|
* GNU Lesser General Public License Version 2.1
|
|
* =============================================
|
|
* Copyright 2000 by Sun Microsystems, Inc.
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library 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 for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
*
|
|
* Sun Industry Standards Source License Version 1.1
|
|
* =================================================
|
|
* The contents of this file are subject to the Sun Industry Standards
|
|
* Source License Version 1.1 (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.openoffice.org/license.html.
|
|
*
|
|
* Software provided under this License is provided on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
|
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
|
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
|
* See the License for the specific provisions governing your rights and
|
|
* obligations concerning the Software.
|
|
*
|
|
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
|
|
*
|
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
|
*
|
|
* All Rights Reserved.
|
|
*
|
|
* Contributor(s): _______________________________________
|
|
*
|
|
*
|
|
************************************************************************/
|
|
|
|
#ifdef PCH
|
|
#include "ui_pch.hxx"
|
|
#endif
|
|
|
|
#pragma hdrstop
|
|
|
|
// INCLUDE ---------------------------------------------------------
|
|
|
|
#include <sfx2/app.hxx>
|
|
#include <sfx2/docfile.hxx>
|
|
#include <svx/linkmgr.hxx>
|
|
#include <svtools/stritem.hxx>
|
|
#include <vcl/msgbox.hxx>
|
|
|
|
#include "arealink.hxx"
|
|
|
|
#include "tablink.hxx"
|
|
#include "document.hxx"
|
|
#include "docsh.hxx"
|
|
#include "rangenam.hxx"
|
|
#include "dbcolect.hxx"
|
|
#include "undoblk.hxx"
|
|
#include "globstr.hrc"
|
|
#include "markdata.hxx"
|
|
#include "hints.hxx"
|
|
|
|
#include "attrib.hxx" // raus, wenn ResetAttrib am Dokument
|
|
#include "patattr.hxx" // raus, wenn ResetAttrib am Dokument
|
|
#include "docpool.hxx" // raus, wenn ResetAttrib am Dokument
|
|
|
|
TYPEINIT1(ScAreaLink,SvBaseLink);
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
ScAreaLink::ScAreaLink( SfxObjectShell* pShell, const String& rFile,
|
|
const String& rFilter, const String& rOpt,
|
|
const String& rArea, const ScRange& rDest ) :
|
|
SvBaseLink (LINKUPDATE_ONCALL,FORMAT_FILE),
|
|
pDocShell ((ScDocShell*)pShell),
|
|
aFileName (rFile),
|
|
aFilterName (rFilter),
|
|
aOptions (rOpt),
|
|
aSourceArea (rArea),
|
|
aDestArea (rDest),
|
|
bAddUndo (TRUE),
|
|
bInCreate (FALSE),
|
|
bDoInsert (TRUE)
|
|
{
|
|
DBG_ASSERT(pShell->ISA(ScDocShell), "ScAreaLink mit falscher ObjectShell");
|
|
}
|
|
|
|
__EXPORT ScAreaLink::~ScAreaLink()
|
|
{
|
|
// Verbindung aufheben
|
|
}
|
|
|
|
BOOL __EXPORT ScAreaLink::Edit(Window* pParent)
|
|
{
|
|
// DefModalDialogParent setzen, weil evtl. aus der DocShell beim ConvertFrom
|
|
// ein Optionen-Dialog kommt...
|
|
|
|
Window* pOldParent = Application::GetDefDialogParent();
|
|
if (pParent)
|
|
Application::SetDefDialogParent(pParent);
|
|
|
|
BOOL bRet = SvBaseLink::Edit(pParent);
|
|
|
|
Application::SetDefDialogParent(pOldParent);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
void __EXPORT ScAreaLink::DataChanged(SvData& rData)
|
|
{
|
|
// bei bInCreate nichts tun, damit Update gerufen werden kann, um den Status im
|
|
// LinkManager zu setzen, ohne die Daten im Dokument zu aendern
|
|
|
|
if (bInCreate)
|
|
return;
|
|
|
|
SvxLinkManager* pLinkManager=pDocShell->GetDocument()->GetLinkManager();
|
|
if (pLinkManager!=NULL)
|
|
{
|
|
String aFile;
|
|
String aFilter;
|
|
String aArea;
|
|
pLinkManager->GetDisplayNames(*this,0,&aFile,&aArea,&aFilter);
|
|
|
|
// aus dem Dialog kommt der Filtername mit Applikation davor
|
|
//! soll das so sein ??!?!
|
|
String aAppPrefix = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( STRING_SCAPP ));
|
|
aAppPrefix.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ": " ));
|
|
xub_StrLen nPreLen = aAppPrefix.Len();
|
|
if ( aFilter.Copy(0,nPreLen) == aAppPrefix )
|
|
aFilter.Erase(0,nPreLen);
|
|
|
|
// #81155# dialog doesn't set area, so keep old one
|
|
if ( !aArea.Len() )
|
|
{
|
|
aArea = aSourceArea;
|
|
|
|
// adjust in dialog:
|
|
String aLinkName;
|
|
MakeLnkName( aLinkName, NULL, aFile, aArea, &aFilter );
|
|
SetName( new SvLinkName( aLinkName ) );
|
|
}
|
|
|
|
Refresh(aFile,aFilter,aArea);
|
|
}
|
|
}
|
|
|
|
void __EXPORT ScAreaLink::Closed()
|
|
{
|
|
// Verknuepfung loeschen: Undo
|
|
|
|
ScDocument* pDoc = pDocShell->GetDocument();
|
|
BOOL bUndo (pDoc->IsUndoEnabled());
|
|
if (bAddUndo && bUndo)
|
|
{
|
|
pDocShell->GetUndoManager()->AddUndoAction( new ScUndoRemoveAreaLink( pDocShell,
|
|
aFileName, aFilterName, aOptions,
|
|
aSourceArea, aDestArea ) );
|
|
|
|
bAddUndo = FALSE; // nur einmal
|
|
}
|
|
|
|
SvBaseLink::Closed();
|
|
}
|
|
|
|
void ScAreaLink::SetDestArea(const ScRange& rNew)
|
|
{
|
|
aDestArea = rNew; // fuer Undo
|
|
}
|
|
|
|
void ScAreaLink::SetSource(const String& rDoc, const String& rFlt, const String& rOpt,
|
|
const String& rArea)
|
|
{
|
|
aFileName = rDoc;
|
|
aFilterName = rFlt;
|
|
aOptions = rOpt;
|
|
aSourceArea = rArea;
|
|
}
|
|
|
|
BOOL ScAreaLink::IsEqual( const String& rFile, const String& rFilter, const String& rOpt,
|
|
const String& rSource, const ScRange& rDest ) const
|
|
{
|
|
return aFileName == rFile && aFilterName == rFilter && aOptions == rOpt &&
|
|
aSourceArea == rSource && aDestArea == rDest;
|
|
}
|
|
|
|
// ausfuehren:
|
|
|
|
BOOL ScAreaLink::Refresh( const String& rNewFile, const String& rNewFilter,
|
|
const String& rNewArea )
|
|
{
|
|
// Dokument laden - wie TabLink
|
|
|
|
if (!rNewFile.Len() || !rNewFilter.Len())
|
|
return FALSE;
|
|
|
|
String aNewUrl( ScGlobal::GetAbsDocName( rNewFile, pDocShell ) );
|
|
BOOL bNewUrlName = (aNewUrl != aFileName);
|
|
|
|
const SfxFilter* pFilter = SFX_APP()->GetFilter( pDocShell->GetFactory(), rNewFilter );
|
|
if (!pFilter)
|
|
return FALSE;
|
|
|
|
ScDocument* pDoc = pDocShell->GetDocument();
|
|
|
|
BOOL bUndo (pDoc->IsUndoEnabled());
|
|
pDoc->SetInLinkUpdate( TRUE );
|
|
|
|
// wenn neuer Filter ausgewaehlt wurde, Optionen vergessen
|
|
if ( rNewFilter != aFilterName )
|
|
aOptions.Erase();
|
|
|
|
// ItemSet immer anlegen, damit die DocShell die Optionen setzen kann
|
|
SfxItemSet* pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
|
|
if ( aOptions.Len() )
|
|
pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, aOptions ) );
|
|
|
|
SfxMedium* pMed = new SfxMedium(aNewUrl, STREAM_STD_READ, FALSE, pFilter);
|
|
|
|
ScDocShell* pSrcShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL);
|
|
SvEmbeddedObjectRef aRef = pSrcShell;
|
|
pSrcShell->DoLoad(pMed);
|
|
|
|
// Optionen koennten gesetzt worden sein
|
|
String aNewOpt = ScDocumentLoader::GetOptions(*pMed);
|
|
if (!aNewOpt.Len())
|
|
aNewOpt = aOptions;
|
|
|
|
// Bereich suchen
|
|
|
|
BOOL bFound = FALSE;
|
|
ScRange aSourceRange;
|
|
ScDocument* pSrcDoc = pSrcShell->GetDocument();
|
|
ScRangeName* pNames = pSrcDoc->GetRangeName();
|
|
USHORT nPos;
|
|
if (pNames) // benannte Bereiche
|
|
{
|
|
if (pNames->SearchName( rNewArea, nPos ))
|
|
if ( (*pNames)[nPos]->IsReference( aSourceRange ) )
|
|
bFound = TRUE;
|
|
}
|
|
if (!bFound) // Datenbankbereiche
|
|
{
|
|
ScDBCollection* pDBColl = pSrcDoc->GetDBCollection();
|
|
if (pDBColl)
|
|
if (pDBColl->SearchName( rNewArea, nPos ))
|
|
{
|
|
USHORT nTab,nCol1,nRow1,nCol2,nRow2;
|
|
(*pDBColl)[nPos]->GetArea(nTab,nCol1,nRow1,nCol2,nRow2);
|
|
aSourceRange = ScRange( nCol1,nRow1,nTab, nCol2,nRow2,nTab );
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
if (!bFound) // direct reference (range or cell)
|
|
{
|
|
if ( aSourceRange.ParseAny( rNewArea, pSrcDoc ) & SCA_VALID )
|
|
bFound = TRUE;
|
|
}
|
|
|
|
// alte Daten loeschen / neue kopieren
|
|
|
|
ScAddress aDestPos = aDestArea.aStart;
|
|
USHORT nDestTab = aDestPos.Tab();
|
|
ScRange aOldRange = aDestArea;
|
|
ScRange aNewRange = aDestArea; // alter Bereich, wenn Datei nicht gefunden o.ae.
|
|
if (bFound)
|
|
aNewRange.aEnd = ScAddress(
|
|
aSourceRange.aEnd.Col() - aSourceRange.aStart.Col() + aDestPos.Col(),
|
|
aSourceRange.aEnd.Row() - aSourceRange.aStart.Row() + aDestPos.Row(),
|
|
nDestTab );
|
|
|
|
|
|
BOOL bCanDo = pDoc->CanFitBlock( aOldRange, aNewRange ); //! nach bDoInsert unterscheiden
|
|
if (bCanDo)
|
|
{
|
|
ScDocShellModificator aModificator( *pDocShell );
|
|
|
|
USHORT nStartX = aDestPos.Col();
|
|
USHORT nStartY = aDestPos.Row();
|
|
USHORT nOldEndX = aOldRange.aEnd.Col();
|
|
USHORT nOldEndY = aOldRange.aEnd.Row();
|
|
USHORT nNewEndX = aNewRange.aEnd.Col();
|
|
USHORT nNewEndY = aNewRange.aEnd.Row();
|
|
ScRange aMaxRange( aDestPos,
|
|
ScAddress(Max(nOldEndX,nNewEndX), Max(nOldEndY,nNewEndY), nDestTab) );
|
|
|
|
// Undo initialisieren
|
|
|
|
ScDocument* pUndoDoc = NULL;
|
|
ScDocument* pRedoDoc = NULL;
|
|
if ( bAddUndo && bUndo )
|
|
{
|
|
pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
|
|
if ( bDoInsert )
|
|
{
|
|
if ( nNewEndX != nOldEndX || nNewEndY != nOldEndY ) // Bereich veraendert?
|
|
{
|
|
pUndoDoc->InitUndo( pDoc, 0, pDoc->GetTableCount()-1 );
|
|
pDoc->CopyToDocument( 0,0,0,MAXCOL,MAXROW,MAXTAB,
|
|
IDF_FORMULA, FALSE, pUndoDoc ); // alle Formeln
|
|
}
|
|
else
|
|
pUndoDoc->InitUndo( pDoc, nDestTab, nDestTab ); // nur Zieltabelle
|
|
pDoc->CopyToDocument( aOldRange, IDF_ALL, FALSE, pUndoDoc );
|
|
}
|
|
else // ohne Einfuegen
|
|
{
|
|
pUndoDoc->InitUndo( pDoc, nDestTab, nDestTab ); // nur Zieltabelle
|
|
pDoc->CopyToDocument( aMaxRange, IDF_ALL, FALSE, pUndoDoc );
|
|
}
|
|
}
|
|
|
|
// Zellen einfuegen / loeschen
|
|
// DeleteAreaTab loescht auch MERGE_FLAG Attribute
|
|
|
|
if (bDoInsert)
|
|
pDoc->FitBlock( aOldRange, aNewRange ); // incl. loeschen
|
|
else
|
|
pDoc->DeleteAreaTab( aMaxRange, IDF_ALL );
|
|
|
|
// Daten kopieren
|
|
|
|
if (bFound)
|
|
{
|
|
USHORT nSrcTab = aSourceRange.aStart.Tab();
|
|
ScMarkData aSourceMark;
|
|
aSourceMark.SelectOneTable( nSrcTab ); // selektieren fuer CopyToClip
|
|
aSourceMark.SetMarkArea( aSourceRange );
|
|
|
|
ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
|
|
pSrcDoc->CopyToClip( aSourceRange.aStart.Col(),aSourceRange.aStart.Row(),
|
|
aSourceRange.aEnd.Col(),aSourceRange.aEnd.Row(),
|
|
FALSE, pClipDoc, FALSE, &aSourceMark );
|
|
|
|
if ( pClipDoc->HasAttrib( 0,0,nSrcTab, MAXCOL,MAXROW,nSrcTab,
|
|
HASATTR_MERGED | HASATTR_OVERLAPPED ) )
|
|
{
|
|
//! ResetAttrib am Dokument !!!
|
|
|
|
ScPatternAttr aPattern( pSrcDoc->GetPool() );
|
|
aPattern.GetItemSet().Put( ScMergeAttr() ); // Defaults
|
|
aPattern.GetItemSet().Put( ScMergeFlagAttr() );
|
|
pClipDoc->ApplyPatternAreaTab( 0,0, MAXCOL,MAXROW, nSrcTab, aPattern );
|
|
}
|
|
|
|
ScMarkData aDestMark;
|
|
aDestMark.SelectOneTable( nDestTab );
|
|
aDestMark.SetMarkArea( aNewRange );
|
|
pDoc->CopyFromClip( aNewRange, aDestMark, IDF_ALL, NULL, pClipDoc, FALSE );
|
|
|
|
delete pClipDoc;
|
|
}
|
|
else
|
|
{
|
|
String aErr = ScGlobal::GetRscString(STR_LINKERROR);
|
|
pDoc->SetString( aDestPos.Col(), aDestPos.Row(), aDestPos.Tab(), aErr );
|
|
}
|
|
|
|
// Undo eintragen
|
|
|
|
if ( bAddUndo && bUndo)
|
|
{
|
|
pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
|
|
pRedoDoc->InitUndo( pDoc, nDestTab, nDestTab );
|
|
pDoc->CopyToDocument( aNewRange, IDF_ALL, FALSE, pRedoDoc );
|
|
|
|
pDocShell->GetUndoManager()->AddUndoAction(
|
|
new ScUndoUpdateAreaLink( pDocShell,
|
|
aFileName, aFilterName, aOptions,
|
|
aSourceArea, aOldRange,
|
|
aNewUrl, rNewFilter, aNewOpt,
|
|
rNewArea, aNewRange,
|
|
pUndoDoc, pRedoDoc, bDoInsert ) );
|
|
}
|
|
|
|
// neue Einstellungen merken
|
|
|
|
if ( bNewUrlName )
|
|
aFileName = aNewUrl;
|
|
if ( rNewFilter != aFilterName )
|
|
aFilterName = rNewFilter;
|
|
if ( rNewArea != aSourceArea )
|
|
aSourceArea = rNewArea;
|
|
if ( aNewOpt != aOptions )
|
|
aOptions = aNewOpt;
|
|
|
|
if ( aNewRange != aDestArea )
|
|
aDestArea = aNewRange;
|
|
|
|
USHORT nPaintEndX = Max( aOldRange.aEnd.Col(), aNewRange.aEnd.Col() );
|
|
USHORT nPaintEndY = Max( aOldRange.aEnd.Row(), aNewRange.aEnd.Row() );
|
|
|
|
if ( aOldRange.aEnd.Col() != aNewRange.aEnd.Col() )
|
|
nPaintEndX = MAXCOL;
|
|
if ( aOldRange.aEnd.Row() != aNewRange.aEnd.Row() )
|
|
nPaintEndY = MAXROW;
|
|
|
|
pDocShell->PostPaint( aDestPos.Col(),aDestPos.Row(),nDestTab,
|
|
nPaintEndX,nPaintEndY,nDestTab, PAINT_GRID );
|
|
aModificator.SetDocumentModified();
|
|
}
|
|
else
|
|
{
|
|
// CanFitBlock FALSE -> Probleme mit zusammengefassten Zellen
|
|
// oder Tabellengrenze erreicht!
|
|
//! Zellschutz ???
|
|
|
|
//! Link-Dialog muss Default-Parent setzen
|
|
// "kann keine Zeilen einfuegen"
|
|
InfoBox aBox( Application::GetDefDialogParent(),
|
|
ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_2 ) );
|
|
aBox.Execute();
|
|
}
|
|
|
|
// aufraeumen
|
|
|
|
aRef->DoClose();
|
|
|
|
pDoc->SetInLinkUpdate( FALSE );
|
|
|
|
if (bCanDo)
|
|
{
|
|
// notify Uno objects (for XRefreshListener)
|
|
//! also notify Uno objects if file name was changed!
|
|
ScLinkRefreshedHint aHint;
|
|
aHint.SetAreaLink( aDestPos );
|
|
pDoc->BroadcastUno( aHint );
|
|
}
|
|
|
|
return bCanDo;
|
|
}
|
|
|
|
|
|
|