/* -*- 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 <config_features.h>
#include <com/sun/star/frame/Desktop.hpp>
#include <scitems.hxx>
#include <editeng/flstitem.hxx>
#include <sfx2/fcontnr.hxx>
#include <sfx2/infobar.hxx>
#include <sfx2/objface.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/sfxresid.hxx>
#include <sfx2/strings.hrc>
#include <svtools/ehdl.hxx>
#include <svtools/langtab.hxx>
#include <basic/sbxcore.hxx>
#include <basic/sberrors.hxx>
#include <svtools/sfxecode.hxx>
#include <svx/ofaitem.hxx>
#include <svx/svdograf.hxx>
#include <svl/stritem.hxx>
#include <svl/whiter.hxx>
#include <vcl/stdtext.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>
#include <svx/dataaccessdescriptor.hxx>
#include <svx/drawitem.hxx>
#include <svx/fmshell.hxx>
#include <sfx2/passwd.hxx>
#include <sfx2/filedlghelper.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/sfxdlg.hxx>
#include <svl/PasswordHelper.hxx>
#include <svl/documentlockfile.hxx>
#include <svl/sharecontrolfile.hxx>
#include <tools/json_writer.hxx>
#include <unotools/securityoptions.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <sal/log.hxx>
#include <unotools/charclass.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <o3tl/string_view.hxx>
#include <comphelper/lok.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/propertyvalue.hxx>
#include <docuno.hxx>
#include <docsh.hxx>
#include "docshimp.hxx"
#include <docfunc.hxx>
#include <scres.hrc>
#include <strings.hrc>
#include <stlsheet.hxx>
#include <stlpool.hxx>
#include <appoptio.hxx>
#include <globstr.hrc>
#include <global.hxx>
#include <dbdocfun.hxx>
#include <printfun.hxx>
#include <viewdata.hxx>
#include <tabvwsh.hxx>
#include <impex.hxx>
#include <undodat.hxx>
#include <undocell.hxx>
#include <inputhdl.hxx>
#include <dbdata.hxx>
#include <servobj.hxx>
#include <rangenam.hxx>
#include <scmod.hxx>
#include <chgviset.hxx>
#include <reffact.hxx>
#include <chartlis.hxx>
#include <chartpos.hxx>
#include <tablink.hxx>
#include <drwlayer.hxx>
#include <docoptio.hxx>
#include <undostyl.hxx>
#include <rangeseq.hxx>
#include <chgtrack.hxx>
#include <com/sun/star/document/UpdateDocMode.hpp>
#include <scresid.hxx>
#include <scabstdlg.hxx>
#include <sharedocdlg.hxx>
#include <conditio.hxx>
#include <sheetevents.hxx>
#include <formulacell.hxx>
#include <documentlinkmgr.hxx>
#include <memory>
#include <sfx2/notebookbar/SfxNotebookBar.hxx>
#include <helpids.h>
#include <editeng/eeitem.hxx>
#include <editeng/langitem.hxx>
#include <officecfg/Office/Common.hxx>
#include <svx/xdef.hxx>
using namespace ::com::sun::star;
void ScDocShell::SetInitialLinkUpdate(
const SfxMedium* pMed )
{
if (pMed)
{
const SfxUInt16Item* pUpdateDocItem = pMed->GetItemSet().GetItem(SID_UPDATEDOCMODE,
false );
m_nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : css::document::UpdateDocMo
de::NO_UPDATE;
}
// GetLinkUpdateModeState() evaluates m_nCanUpdate so that must have
// been set first. Do not override an already forbidden LinkUpdate (the
// default is allow).
comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = getEmbeddedObjectContainer();
if (rEmbeddedObjectContainer.getUserAllowsLinkUpdate())
{
// For anything else than LM_ALWAYS we need user confirmation.
rEmbeddedObjectContainer.setUserAllowsLinkUpdate( GetLinkUpdateModeState() == LM_ALWAYS);
}
}
ScLkUpdMode ScDocShell::GetLinkUpdateModeState() const
{
ScLkUpdMode nSet;
if (m_nCanUpdate == css::document::UpdateDocMode::NO_UPDATE)
nSet = LM_NEVER;
else if (m_nCanUpdate == css::document::UpdateDocMode::FULL_UPDATE)
nSet = LM_ALWAYS;
else
{
nSet = GetDocument().GetLinkMode();
if (nSet == LM_UNKNOWN)
{
ScAppOptions aAppOptions = ScModule::get()->GetAppOptions();
nSet = aAppOptions.GetLinkMode();
}
}
if (nSet != LM_NEVER
&& (SvtSecurityOptions::isUntrustedReferer(
GetMedium() == nullptr ? OUString() : GetMedium()->GetName())
|| (IsDocShared() && SvtSecurityOptions::isUntrustedReferer(GetSharedFileURL()))))
{
nSet = LM_NEVER;
}
else if (nSet == LM_ALWAYS
&& !(SvtSecurityOptions::isTrustedLocationUriForUpdatingLinks(
GetMedium() == nullptr ? OUString() : GetMedium()->GetName())
|| (IsDocShared()
&& SvtSecurityOptions::isTrustedLocationUriForUpdatingLinks(
GetSharedFileURL()))))
{
nSet = LM_ON_DEMAND;
}
if (m_nCanUpdate == css::document::UpdateDocMode::QUIET_UPDATE
&& nSet == LM_ON_DEMAND)
{
nSet = LM_NEVER;
}
return nSet;
}
void ScDocShell::AllowLinkUpdate()
{
m_pDocument->SetLinkFormulaNeedingCheck(false );
getEmbeddedObjectContainer().setUserAllowsLinkUpdate(true );
}
void ScDocShell::ReloadAllLinks()
{
AllowLinkUpdate();
ReloadTabLinks();
weld::Window *pDialogParent = GetActiveDialogParent();
m_pDocument->UpdateExternalRefLinks(pDialogParent);
bool bAnyDde = m_pDocument->GetDocLinkManager().updateDdeOrOleOrWebServiceLinks(pDialogParent);
if (bAnyDde)
{
// calculate formulas and paint like in the TrackTimeHdl
m_pDocument->TrackFormulas();
Broadcast(SfxHint(SfxHintId::ScDataChanged));
// Should FID_DATACHANGED become asynchronous some time
// (e.g., with Invalidate at Window), an update needs to be forced here.
}
m_pDocument->UpdateAreaLinks();
}
IMPL_LINK( ScDocShell, ReloadAllLinksHdl, weld::Button&, rButton, void )
{
ScDocument& rDoc = GetDocument();
if (rDoc.HasLinkFormulaNeedingCheck() && rDoc.GetDocLinkManager().hasExternalRefLinks())
{
// If we have WEBSERVICE/Dde link and other external links in the document, it might indicate some
// exfiltration attempt, add *another* warning about this on top of the "Security Warning"
// shown in the infobar before they got here.
std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(&rButton,
VclMessageType::Warning, VclButtonsType::YesNo,
ScResId(STR_TRUST_DOCUMENT_WARNING)));
xQueryBox->set_secondary_text(ScResId(STR_WEBSERVICE_WITH_LINKS_WARNING));
xQueryBox->set_default_response(RET_NO);
if (xQueryBox->run() != RET_YES)
return ;
}
ReloadAllLinks();
ScTabViewShell* pViewSh = GetBestViewShell();
SfxViewFrame* pViewFrame = pViewSh ? pViewSh->GetFrame() : nullptr;
if (pViewFrame)
pViewFrame->RemoveInfoBar(u"enablecontent" );
SAL_WARN_IF(!pViewFrame, "sc" , "expected there to be a ViewFrame" );
}
namespace
{
class LinkHelp
{
public :
DECL_STATIC_LINK(LinkHelp, DispatchHelpLinksHdl, weld::Button&, void );
};
}
IMPL_STATIC_LINK(LinkHelp, DispatchHelpLinksHdl, weld::Button&, rBtn, void )
{
if (Help* pHelp = Application::GetHelp())
pHelp->Start(HID_UPDATE_LINK_WARNING, &rBtn);
}
void ScDocShell::Execute( SfxRequest& rReq )
{
const SfxItemSet* pReqArgs = rReq.GetArgs();
SfxBindings* pBindings = GetViewBindings();
bool bUndo (m_pDocument->IsUndoEnabled());
sal_uInt16 nSlot = rReq.GetSlot();
switch ( nSlot )
{
case SID_SC_SETTEXT:
{
const SfxPoolItem* pColItem;
const SfxPoolItem* pRowItem;
const SfxPoolItem* pTabItem;
const SfxPoolItem* pTextItem;
if ( pReqArgs && pReqArgs->HasItem( FN_PARAM_1, &pColItem ) &&
pReqArgs->HasItem( FN_PARAM_2, &pRowItem ) &&
pReqArgs->HasItem( FN_PARAM_3, &pTabItem ) &&
pReqArgs->HasItem( SID_SC_SETTEXT, &pTextItem ) )
{
// parameters are 1-based !!!
SCCOL nCol = static_cast <const SfxInt16Item*>(pColItem)->GetValue() - 1;
SCROW nRow = static_cast <const SfxInt32Item*>(pRowItem)->GetValue() - 1;
SCTAB nTab = static_cast <const SfxInt16Item*>(pTabItem)->GetValue() - 1;
SCTAB nTabCount = m_pDocument->GetTableCount();
if ( m_pDocument->ValidCol(nCol) && m_pDocument->ValidRow(nRow) && ValidTab(nTab,nTabCount) )
{
if ( m_pDocument->IsBlockEditable( nTab, nCol,nRow, nCol, nRow ) )
{
OUString aVal = static_cast <const SfxStringItem*>(pTextItem)->GetValue();
m_pDocument->SetString( nCol, nRow, nTab, aVal );
PostPaintCell( nCol, nRow, nTab );
SetDocumentModified();
rReq.Done();
break ;
}
else // protected cell
{
#if HAVE_FEATURE_SCRIPTING
SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER ); //! which error ?
#endif
break ;
}
}
}
#if HAVE_FEATURE_SCRIPTING
SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT );
#endif
}
break ;
case SID_SBA_IMPORT:
{
if (pReqArgs)
{
const SfxPoolItem* pItem;
svx::ODataAccessDescriptor aDesc;
if ( pReqArgs->GetItemState( nSlot, true , &pItem ) == SfxItemState::SET )
{
uno::Any aAny = static_cast <const SfxUnoAnyItem*>(pItem)->GetValue();
uno::Sequence<beans::PropertyValue> aProperties;
if ( aAny >>= aProperties )
aDesc.initializeFrom( aProperties );
}
OUString sTarget;
if ( pReqArgs->GetItemState( FN_PARAM_1, true , &pItem ) == SfxItemState::SET )
sTarget = static_cast <const SfxStringItem*>(pItem)->GetValue();
bool bIsNewArea = true ; // Default sal_True (no inquiry)
if ( pReqArgs->GetItemState( FN_PARAM_2, true , &pItem ) == SfxItemState::SET )
bIsNewArea = static_cast <const SfxBoolItem*>(pItem)->GetValue();
// if necessary, create new database area
bool bMakeArea = false ;
if (bIsNewArea)
{
ScDBCollection* pDBColl = m_pDocument->GetDBCollection();
if ( !pDBColl || !pDBColl->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(sTarget)) )
{
ScAddress aPos;
if ( aPos.Parse( sTarget, *m_pDocument, m_pDocument->GetAddressConvention() ) & ScRefFlags::VALID )
{
bMakeArea = true ;
if (bUndo)
{
OUString aStrImport = ScResId( STR_UNDO_IMPORTDATA );
ViewShellId nViewShellId(-1);
if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell())
nViewShellId = pViewSh->GetViewShellId();
GetUndoManager()->EnterListAction( aStrImport, aStrImport, 0, nViewShellId );
}
ScDBData* pDBData = GetDBData( ScRange(aPos), SC_DB_IMPORT, ScGetDBSelection::Keep );
assert(pDBData && "Cannot create DB data" );
sTarget = pDBData->GetName();
}
}
}
// inquire, before old DB range gets overwritten
bool bDo = true ;
if (!bIsNewArea)
{
OUString aTemplate = ScResId( STR_IMPORT_REPLACE );
OUString aMessage = o3tl::getToken(aTemplate, 0, '#' )
+ sTarget
+ o3tl::getToken(aTemplate, 1, '#' );
std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr,
VclMessageType::Question, VclButtonsType::YesNo,
aMessage));
xQueryBox->set_default_response(RET_YES);
bDo = xQueryBox->run() == RET_YES;
}
if (bDo)
{
ScDBDocFunc(*this ).UpdateImport( sTarget, aDesc );
rReq.Done();
// UpdateImport also updates the internal operations
}
else
rReq.Ignore();
if ( bMakeArea && bUndo)
GetUndoManager()->LeaveListAction();
}
else
{
OSL_FAIL( "arguments expected" );
}
}
break ;
case SID_CHART_SOURCE:
case SID_CHART_ADDSOURCE:
ExecuteChartSource(rReq);
break ;
case FID_AUTO_CALC:
{
bool bNewVal;
const SfxPoolItem* pItem;
if ( pReqArgs && SfxItemState::SET == pReqArgs->GetItemState( nSlot, true , &pItem ) )
bNewVal = static_cast <const SfxBoolItem*>(pItem)->GetValue();
else
bNewVal = !m_pDocument->GetAutoCalc(); // Toggle for menu
m_pDocument->SetAutoCalc( bNewVal );
SetDocumentModified();
if (pBindings)
{
pBindings->Invalidate( FID_AUTO_CALC );
}
rReq.AppendItem( SfxBoolItem( FID_AUTO_CALC, bNewVal ) );
rReq.Done();
}
break ;
case SID_OPEN_HYPERLINK:
{
ScViewData* pViewData = GetViewData();
if ( !pViewData )
{
rReq.Ignore();
break ;
}
if (ScModule::get()->IsEditMode())
{
if (EditView* pEditView = pViewData->GetEditView(pViewData->GetActivePart()))
{
const SvxFieldItem* pFieldItem = pEditView->GetFieldAtSelection(/*bAlsoCheckBeforeCursor=*/true);
const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr;
if (const SvxURLField* pURLField = dynamic_cast <const SvxURLField*>(pField))
{
ScGlobal::OpenURL(pURLField->GetURL(), pURLField->GetTargetFrame(), true );
rReq.Done();
break ;
}
}
rReq.Ignore();
break ;
}
ScGridWindow* pWin = pViewData->GetActiveWin();
if ( !pWin )
{
rReq.Ignore();
break ;
}
ScAddress aCell {pViewData->GetCurPos()};
std::vector<UrlData> vUrls = pWin->GetEditUrls(aCell);
if (vUrls.empty())
{
rReq.Ignore();
break ;
}
for (UrlData& data : vUrls)
{
ScGlobal::OpenURL(data.aUrl, data.aTarget, true );
}
rReq.Done();
}
break ;
case FID_RECALC:
DoRecalc( rReq.IsAPI() );
rReq.Done();
break ;
case FID_HARD_RECALC:
DoHardRecalc();
rReq.Done();
break ;
case SID_UPDATETABLINKS:
{
ScLkUpdMode nSet = GetLinkUpdateModeState();
if (nSet == LM_ALWAYS)
{
ReloadAllLinks();
rReq.Done();
}
else if (nSet == LM_NEVER)
{
getEmbeddedObjectContainer().setUserAllowsLinkUpdate(false );
rReq.Ignore();
}
else if (nSet == LM_ON_DEMAND)
{
ScTabViewShell* pViewSh = GetBestViewShell();
SfxViewFrame* pViewFrame = pViewSh ? pViewSh->GetFrame() : nullptr;
if (pViewFrame)
{
pViewFrame->RemoveInfoBar(u"enablecontent" );
auto pInfoBar = pViewFrame->AppendInfoBar(u"enablecontent" _ustr, SfxResId(RID_SECURITY_WARNING_TITLE),
ScResId(STR_RELOAD_TABLES), InfobarType::WARNING);
if (pInfoBar)
{
weld::Button& rHelpBtn = pInfoBar->addButton();
rHelpBtn.set_label(GetStandardText(StandardButtonType::Help).replaceFirst("~" , "" ));
rHelpBtn.connect_clicked(LINK(nullptr, LinkHelp, DispatchHelpLinksHdl));
weld::Button& rBtn = pInfoBar->addButton();
rBtn.set_label(ScResId(STR_ENABLE_CONTENT));
rBtn.set_tooltip_text(ScResId(STR_ENABLE_CONTENT_TOOLTIP));
rBtn.connect_clicked(LINK(this , ScDocShell, ReloadAllLinksHdl));
// when active content is disabled the "Allow updating" button has no functionality.
if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get())
{
rBtn.set_tooltip_text(ScResId(STR_ENABLE_CONTENT_TOOLTIP_DISABLED));
rBtn.set_sensitive(false );
}
}
}
rReq.Done();
}
}
break ;
case SID_REIMPORT_AFTER_LOAD:
{
// Is called after loading if there are DB areas with omitted data
bool bDone = false ;
ScDBCollection* pDBColl = m_pDocument->GetDBCollection();
if ((m_nCanUpdate != css::document::UpdateDocMode::NO_UPDATE) &&
(m_nCanUpdate != css::document::UpdateDocMode::QUIET_UPDATE))
{
ScRange aRange;
ScTabViewShell* pViewSh = GetBestViewShell();
OSL_ENSURE(pViewSh,"SID_REIMPORT_AFTER_LOAD: no View" );
if (pViewSh && pDBColl)
{
std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetActiveDialogParent(),
VclMessageType::Question, VclButtonsType::YesNo,
ScResId(STR_REIMPORT_AFTER_LOAD)));
xQueryBox->set_default_response(RET_YES);
if (xQueryBox->run() == RET_YES)
{
ScDBCollection::NamedDBs& rDBs = pDBColl->getNamedDBs();
for (const auto & rxDB : rDBs)
{
ScDBData& rDBData = *rxDB;
if ( rDBData.IsStripData() &&
rDBData.HasImportParam() && !rDBData.HasImportSelection() )
{
rDBData.GetArea(aRange);
pViewSh->MarkRange(aRange);
// Import and internal operations like SID_REFRESH_DBAREA
// (inquiry for import not needed here)
ScImportParam aImportParam;
rDBData.GetImportParam( aImportParam );
bool bContinue = pViewSh->ImportData( aImportParam );
rDBData.SetImportParam( aImportParam );
// mark (size may have changed)
rDBData.GetArea(aRange);
pViewSh->MarkRange(aRange);
if ( bContinue ) // error at import -> abort
{
// internal operations, if some where saved
if ( rDBData.HasQueryParam() || rDBData.HasSortParam() ||
rDBData.HasSubTotalParam() )
pViewSh->RepeatDB();
// pivot tables, which have the range as source data
RefreshPivotTables(aRange);
}
}
}
bDone = true ;
}
}
}
if ( !bDone && pDBColl )
{
// if not, but then update the dependent formulas
//! also for individual ranges, which cannot be updated
m_pDocument->CalcAll(); //! only for the dependent
PostDataChanged();
}
if (bDone)
rReq.Done();
else
rReq.Ignore();
}
break ;
case SID_AUTO_STYLE:
OSL_FAIL("use ScAutoStyleHint instead of SID_AUTO_STYLE" );
break ;
case SID_GET_COLORLIST:
{
const SvxColorListItem* pColItem = GetItem(SID_COLOR_TABLE);
const XColorListRef& pList = pColItem->GetColorList();
rReq.SetReturnValue(OfaXColorListItem(SID_GET_COLORLIST, pList));
}
break ;
case FID_CHG_RECORD:
{
ScDocument& rDoc = GetDocument();
// get argument (recorded macro)
const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(FID_CHG_RECORD);
bool bDo = true ;
// desired state
ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
bool bActivateTracking = (pChangeTrack == nullptr); // toggle
if ( pItem )
bActivateTracking = pItem->GetValue(); // from argument
if ( !bActivateTracking )
{
if ( !pItem )
{
// no dialog on playing the macro
std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetActiveDialogParent(),
VclMessageType::Warning, VclButtonsType::YesNo,
ScResId(STR_END_REDLINING)));
xWarn->set_default_response(RET_NO);
bDo = (xWarn->run() == RET_YES );
}
if ( bDo )
{
if (pChangeTrack)
{
if ( pChangeTrack->IsProtected() )
bDo = ExecuteChangeProtectionDialog();
}
if ( bDo )
{
rDoc.EndChangeTracking();
PostPaintGridAll();
}
}
}
else
{
rDoc.StartChangeTracking();
ScChangeViewSettings aChangeViewSet;
aChangeViewSet.SetShowChanges(true );
rDoc.SetChangeViewSettings(aChangeViewSet);
}
if ( bDo )
{
UpdateAcceptChangesDialog();
// invalidate slots
if (pBindings)
pBindings->InvalidateAll(false );
if ( !pItem )
rReq.AppendItem( SfxBoolItem( FID_CHG_RECORD, bActivateTracking ) );
rReq.Done();
}
else
rReq.Ignore();
}
break ;
case SID_CHG_PROTECT :
{
if ( ExecuteChangeProtectionDialog() )
{
rReq.Done();
SetDocumentModified();
}
else
rReq.Ignore();
}
break ;
case SID_DOCUMENT_MERGE:
case SID_DOCUMENT_COMPARE:
{
bool bDo = true ;
ScChangeTrack* pChangeTrack = m_pDocument->GetChangeTrack();
if ( pChangeTrack && !m_pImpl->bIgnoreLostRedliningWarning )
{
if ( nSlot == SID_DOCUMENT_COMPARE )
{ //! old changes trace will be lost
std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetActiveDialogParent(),
VclMessageType::Warning, VclButtonsType::YesNo,
ScResId(STR_END_REDLINING)));
xWarn->set_default_response(RET_NO);
if (xWarn->run() == RET_YES)
bDo = ExecuteChangeProtectionDialog( true );
else
bDo = false ;
}
else // merge might reject some actions
bDo = ExecuteChangeProtectionDialog( true );
}
if ( !bDo )
{
rReq.Ignore();
break ;
}
SfxApplication* pApp = SfxGetpApp();
const SfxPoolItem* pItem;
const SfxStringItem* pFileNameItem(nullptr);
SfxMedium* pMed = nullptr;
if (pReqArgs)
pFileNameItem = pReqArgs->GetItemIfSet(SID_FILE_NAME);
if (pFileNameItem)
{
OUString aFileName = pFileNameItem->GetValue();
OUString aFilterName;
if (const SfxStringItem* pFilterItem = pReqArgs->GetItemIfSet(SID_FILTER_NAME))
{
aFilterName = pFilterItem->GetValue();
}
OUString aOptions;
if (const SfxStringItem* pOptionsItem = pReqArgs->GetItemIfSet(SID_FILE_FILTEROPTIONS))
{
aOptions = pOptionsItem->GetValue();
}
short nVersion = 0;
const SfxInt16Item* pInt16Item(nullptr);
if (pReqArgs->GetItemState(SID_VERSION, true , &pItem) == SfxItemState::SET)
pInt16Item = dynamic_cast <const SfxInt16Item*>(pItem);
if (pInt16Item)
{
nVersion = pInt16Item->GetValue();
}
// no filter specified -> detection
if (aFilterName.isEmpty())
ScDocumentLoader::GetFilterName( aFileName, aFilterName, aOptions, true , false );
// filter name from dialog contains application prefix,
// GetFilter needs name without the prefix.
ScDocumentLoader::RemoveAppPrefix( aFilterName );
std::shared_ptr<const SfxFilter> pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName( aFilterName );
auto pSet = std::make_shared<SfxAllItemSet>( pApp->GetPool() );
if (!aOptions.isEmpty())
pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, aOptions ) );
if ( nVersion != 0 )
pSet->Put( SfxInt16Item( SID_VERSION, nVersion ) );
pMed = new SfxMedium( aFileName, StreamMode::STD_READ, std::move(pFilter), std::move(pSet) );
}
else
{
const sfx2::DocumentInserter::Mode mode { nSlot==SID_DOCUMENT_COMPARE
? sfx2::DocumentInserter::Mode::Compare
: sfx2::DocumentInserter::Mode::Merge};
// start file dialog asynchronous
m_pImpl->bIgnoreLostRedliningWarning = true ;
m_pImpl->pRequest.reset(new SfxRequest( rReq ));
m_pImpl->pDocInserter.reset();
ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
weld::Window* pParent = pViewSh ? pViewSh->GetFrameWeld() : nullptr;
m_pImpl->pDocInserter.reset( new ::sfx2::DocumentInserter(pParent,
ScDocShell::Factory().GetFactoryName(), mode ) );
m_pImpl->pDocInserter->StartExecuteModal( LINK( this , ScDocShell, DialogClosedHdl ) );
return ;
}
// now execute in earnest...
SfxErrorContext aEc( ERRCTX_SFX_OPENDOC, pMed->GetName() );
// pOtherDocSh->DoClose() will be called explicitly later, but it is still more safe to use SfxObjectShellLock here
rtl::Reference<ScDocShell> pOtherDocSh = new ScDocShell;
pOtherDocSh->DoLoad( pMed );
ErrCodeMsg nErr = pOtherDocSh->GetErrorCode();
if (nErr)
ErrorHandler::HandleError( nErr ); // also warnings
if ( !pOtherDocSh->GetErrorIgnoreWarning() ) // only errors
{
bool bHadTrack = ( m_pDocument->GetChangeTrack() != nullptr );
#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
sal_uLong nStart = 0;
if ( nSlot == SID_DOCUMENT_MERGE && pChangeTrack )
{
nStart = pChangeTrack->GetActionMax() + 1;
}
#endif
if ( nSlot == SID_DOCUMENT_COMPARE )
CompareDocument( pOtherDocSh->GetDocument() );
else
MergeDocument( pOtherDocSh->GetDocument() );
// show "accept changes" dialog
//! get view for this document!
if ( !IsDocShared() )
{
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
if ( pViewFrm )
{
pViewFrm->ShowChildWindow( ScAcceptChgDlgWrapper::GetChildWindowId() ); //@51669
}
if ( pBindings )
{
pBindings->Invalidate( FID_CHG_ACCEPT );
}
}
rReq.SetReturnValue( SfxInt32Item( TypedWhichId<SfxInt32Item>(nSlot), 0 ) ); //! ???????
rReq.Done();
if (!bHadTrack) // newly turned on -> show as well
{
ScChangeViewSettings* pOldSet = m_pDocument->GetChangeViewSettings();
if ( !pOldSet || !pOldSet->ShowChanges() )
{
ScChangeViewSettings aChangeViewSet;
aChangeViewSet.SetShowChanges(true );
m_pDocument->SetChangeViewSettings(aChangeViewSet);
}
}
#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
else if ( nSlot == SID_DOCUMENT_MERGE && IsDocShared() && pChangeTrack )
{
sal_uLong nEnd = pChangeTrack->GetActionMax();
if ( nEnd >= nStart )
{
// only show changes from merged document
ScChangeViewSettings aChangeViewSet;
aChangeViewSet.SetShowChanges( true );
aChangeViewSet.SetShowAccepted( true );
aChangeViewSet.SetHasActionRange();
aChangeViewSet.SetTheActionRange( nStart, nEnd );
m_pDocument->SetChangeViewSettings( aChangeViewSet );
// update view
PostPaintExtras();
PostPaintGridAll();
}
}
#endif
}
pOtherDocSh->DoClose(); // delete happens with the Ref
}
break ;
case SID_DELETE_SCENARIO:
if (pReqArgs)
{
const SfxPoolItem* pItem;
if ( pReqArgs->GetItemState( nSlot, true , &pItem ) == SfxItemState::SET )
{
if (const SfxStringItem* pStringItem = dynamic_cast <const SfxStringItem*>(pItem))
{
const OUString& aName = pStringItem->GetValue();
SCTAB nTab;
if (m_pDocument->GetTable( aName, nTab ))
{
// move DeleteTable from viewfunc to docfunc!
ScTabViewShell* pSh = GetBestViewShell();
if ( pSh )
{
//! omit SetTabNo in DeleteTable?
SCTAB nDispTab = pSh->GetViewData().GetTabNo();
pSh->DeleteTable( nTab );
pSh->SetTabNo(nDispTab);
rReq.Done();
}
}
}
}
}
break ;
case SID_EDIT_SCENARIO:
{
const SfxPoolItem* pItem;
if ( pReqArgs->GetItemState( nSlot, true , &pItem ) == SfxItemState::SET )
{
if (const SfxStringItem* pStringItem = dynamic_cast <const SfxStringItem*>(pItem))
{
OUString aName = pStringItem->GetValue();
SCTAB nTab;
if (m_pDocument->GetTable( aName, nTab ))
{
if (m_pDocument->IsScenario(nTab))
{
OUString aComment;
Color aColor;
ScScenarioFlags nFlags;
m_pDocument->GetScenarioData( nTab, aComment, aColor, nFlags );
// Determine if the Sheet that the Scenario was created on
// is protected. But first we need to find that Sheet.
// Rewind back to the actual sheet.
SCTAB nActualTab = nTab;
do
{
nActualTab--;
}
while (m_pDocument->IsScenario(nActualTab));
bool bSheetProtected = m_pDocument->IsTabProtected(nActualTab);
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
ScopedVclPtr<AbstractScNewScenarioDlg> pNewDlg(pFact->CreateScNewScenarioDlg(GetActiveDialogParent(), aName, true , bSheetProtected));
pNewDlg->SetScenarioData( aName, aComment, aColor, nFlags );
if ( pNewDlg->Execute() == RET_OK )
{
pNewDlg->GetScenarioData( aName, aComment, aColor, nFlags );
ModifyScenario( nTab, aName, aComment, aColor, nFlags );
rReq.Done();
}
}
}
}
}
}
break ;
case SID_ATTR_YEAR2000 :
{
const SfxPoolItem* pItem;
if ( pReqArgs->GetItemState( nSlot, true , &pItem ) == SfxItemState::SET )
{
if (const SfxUInt16Item* pInt16Item = dynamic_cast <const SfxUInt16Item*>(pItem))
{
sal_uInt16 nY2k = pInt16Item->GetValue();
// set always to DocOptions, so that it is also saved for S050
// (and all inquiries run up until now on it as well).
// SetDocOptions propagates that to the NumberFormatter
ScDocOptions aDocOpt( m_pDocument->GetDocOptions() );
aDocOpt.SetYear2000( nY2k );
m_pDocument->SetDocOptions( aDocOpt );
// the FormShell shall notice it as well
ScTabViewShell* pSh = GetBestViewShell();
if ( pSh )
{
FmFormShell* pFSh = pSh->GetFormShell();
if ( pFSh )
pFSh->SetY2KState( nY2k );
}
}
}
}
break ;
#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
case SID_SHARE_DOC:
{
ScViewData* pViewData = GetViewData();
if ( !pViewData )
{
rReq.Ignore();
break ;
}
weld::Window* pWin = GetActiveDialogParent();
ScShareDocumentDlg aDlg(pWin, *pViewData);
if (aDlg.run() == RET_OK)
{
bool bSetShared = aDlg.IsShareDocumentChecked();
if ( bSetShared != IsDocShared() )
{
if ( bSetShared )
{
bool bContinue = true ;
if ( HasName() )
{
std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pWin,
VclMessageType::Question, VclButtonsType::YesNo,
ScResId(STR_DOC_WILLBESAVED)));
xQueryBox->set_default_response(RET_YES);
if (xQueryBox->run() == RET_NO)
{
bContinue = false ;
}
}
if ( bContinue )
{
EnableSharedSettings( true );
ScModule* mod = ScModule::get();
mod->SetInSharedDocSaving(true );
if ( !SwitchToShared( true , true ) )
{
// TODO/LATER: what should be done in case the switch has failed?
// for example in case the user has cancelled the saveAs operation
}
mod->SetInSharedDocSaving(false );
InvalidateName();
GetUndoManager()->Clear();
ScTabView* pTabView = pViewData->GetView();
if ( pTabView )
{
pTabView->UpdateLayerLocks();
}
}
}
else
{
uno::Reference< frame::XModel > xModel;
try
{
// load shared file
xModel.set( LoadSharedDocument(), uno::UNO_SET_THROW );
uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY_THROW );
// check if shared flag is set in shared file
bool bShared = false ;
ScModelObj* pDocObj = comphelper::getFromUnoTunnel<ScModelObj>( xModel );
if ( pDocObj )
{
ScDocShell* pDocShell = dynamic_cast < ScDocShell* >( pDocObj->GetEmbeddedObject() );
if ( pDocShell )
{
bShared = pDocShell->HasSharedXMLFlagSet();
}
}
// #i87870# check if shared status was disabled and enabled again
bool bOwnEntry = false ;
try
{
::svt::ShareControlFile aControlFile( GetSharedFileURL() );
bOwnEntry = aControlFile.HasOwnEntry();
}
catch ( uno::Exception& )
{
}
if ( bShared && bOwnEntry )
{
uno::Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY_THROW );
if ( xStorable->isReadonly() )
{
xCloseable->close( true );
OUString aUserName( ScResId( STR_UNKNOWN_USER ) );
try
{
::svt::DocumentLockFile aLockFile( GetSharedFileURL() );
LockFileEntry aData = aLockFile.GetLockData();
if ( !aData[LockFileComponent::OOOUSERNAME].isEmpty() )
{
aUserName = aData[LockFileComponent::OOOUSERNAME];
}
else if ( !aData[LockFileComponent::SYSUSERNAME].isEmpty() )
{
aUserName = aData[LockFileComponent::SYSUSERNAME];
}
}
catch ( uno::Exception& )
{
}
OUString aMessage( ScResId( STR_FILE_LOCKED_TRY_LATER ) );
aMessage = aMessage.replaceFirst( "%1" , aUserName );
std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin,
VclMessageType::Warning, VclButtonsType::Ok,
aMessage));
xWarn->run();
}
else
{
std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin,
VclMessageType::Warning, VclButtonsType::YesNo,
ScResId(STR_DOC_DISABLESHARED)));
xWarn->set_default_response(RET_YES);
if (xWarn->run() == RET_YES)
{
xCloseable->close( true );
if ( !SwitchToShared( false , true ) )
{
// TODO/LATER: what should be done in case the switch has failed?
// for example in case the user has cancelled the saveAs operation
}
EnableSharedSettings( false );
// Do *not* use dispatch mechanism in this place - we don't want others (extensions etc.) to intercept this.
GetModel()->store();
ScTabView* pTabView = pViewData->GetView();
if ( pTabView )
{
pTabView->UpdateLayerLocks();
}
}
else
{
xCloseable->close( true );
}
}
}
else
{
xCloseable->close( true );
std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin,
VclMessageType::Warning, VclButtonsType::Ok,
ScResId(STR_DOC_NOLONGERSHARED)));
xWarn->run();
}
}
catch ( uno::Exception& )
{
TOOLS_WARN_EXCEPTION( "sc" , "SID_SHARE_DOC" );
ScModule::get()->SetInSharedDocSaving(false );
try
{
uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
xClose->close( true );
}
catch ( uno::Exception& )
{
}
}
}
}
}
rReq.Done();
}
break ;
#endif
case SID_OPEN_CALC:
{
ScViewData* pViewData = GetViewData();
if (pViewData)
{
SfxStringItem aApp(SID_DOC_SERVICE, u"com.sun.star.sheet.SpreadsheetDocument" _ustr);
SfxStringItem aTarget(SID_TARGETNAME, u"_blank" _ustr);
pViewData->GetDispatcher().ExecuteList(
SID_OPENDOC, SfxCallMode::API|SfxCallMode::SYNCHRON,
{ &aApp, &aTarget });
}
}
break ;
case SID_NOTEBOOKBAR:
{
const SfxStringItem* pFile = rReq.GetArg<SfxStringItem>( SID_NOTEBOOKBAR );
if ( pBindings && sfx2::SfxNotebookBar::IsActive() )
sfx2::SfxNotebookBar::ExecMethod(*pBindings, pFile ? pFile->GetValue() : u"" _ustr);
else if ( pBindings )
sfx2::SfxNotebookBar::CloseMethod(*pBindings);
}
break ;
case SID_LANGUAGE_STATUS:
{
OUString aLangText;
const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(nSlot);
if ( pItem )
aLangText = pItem->GetValue();
if ( !aLangText.isEmpty() )
{
LanguageType eLang, eLatin, eCjk, eCtl;
static constexpr OUString aSelectionLangPrefix(u"Current_" _ustr);
static constexpr OUString aParagraphLangPrefix(u"Paragraph_" _ustr);
static constexpr OUString aDocLangPrefix(u"Default_" _ustr);
bool bSelection = false ;
bool bParagraph = false ;
ScDocument& rDoc = GetDocument();
rDoc.GetLanguage( eLatin, eCjk, eCtl );
sal_Int32 nPos = 0;
if ( aLangText == "*" )
{
if (ScTabViewShell* pSh = GetBestViewShell())
{
pSh->ExecuteCellFormatDlg(rReq, u"font" _ustr);
pBindings->Invalidate(SID_LANGUAGE_STATUS);
}
}
else if ( (nPos = aLangText.indexOf(aDocLangPrefix)) != -1 )
{
aLangText = aLangText.replaceAt(nPos, aDocLangPrefix.getLength(), u"" );
if ( aLangText == "LANGUAGE_NONE" )
{
eLang = LANGUAGE_NONE;
rDoc.SetLanguage( eLang, eCjk, eCtl );
}
else if ( aLangText == "RESET_LANGUAGES" )
{
ScModule::GetSpellSettings(eLang, eCjk, eCtl);
rDoc.SetLanguage(eLang, eCjk, eCtl);
}
else
{
eLang = SvtLanguageTable::GetLanguageType( aLangText );
if ( eLang != LANGUAGE_DONTKNOW && SvtLanguageOptions::GetScriptTypeOfLanguage(eLang) == SvtScriptType::LATIN )
{
rDoc.SetLanguage( eLang, eCjk, eCtl );
}
else
{
eLang = eLatin;
}
}
}
else if (-1 != (nPos = aLangText.indexOf( aSelectionLangPrefix )))
{
bSelection = true ;
aLangText = aLangText.replaceAt( nPos, aSelectionLangPrefix.getLength(), u"" );
}
else if (-1 != (nPos = aLangText.indexOf( aParagraphLangPrefix )))
{
bParagraph = true ;
aLangText = aLangText.replaceAt( nPos, aParagraphLangPrefix.getLength(), u"" );
}
if (bSelection)
{
ScTabViewShell* pViewShell = GetBestViewShell();
if (pViewShell)
{
const ScPatternAttr* pSelAttrs = pViewShell->GetSelectionPattern();
if (pSelAttrs)
{
const SfxItemSet& rOldSet = pSelAttrs->GetItemSet();
SfxItemPool* pItemPool = rOldSet.GetPool();
auto pNewSet = std::make_shared<SfxItemSet>(*pItemPool);
if (aLangText == "LANGUAGE_NONE" )
{
pNewSet->Put(SvxLanguageItem(LANGUAGE_NONE,
pItemPool->GetWhichIDFromSlotID(SID_ATTR_CHAR_LANGUAGE)));
pNewSet->Put(SvxLanguageItem(LANGUAGE_NONE,
pItemPool->GetWhichIDFromSlotID(SID_ATTR_CHAR_CJK_LANGUAGE)));
pNewSet->Put(SvxLanguageItem(LANGUAGE_NONE,
pItemPool->GetWhichIDFromSlotID(SID_ATTR_CHAR_CTL_LANGUAGE)));
}
else
{
const LanguageType nLangType = SvtLanguageTable::GetLanguageType(aLangText);
const SvtScriptType nScriptType =
SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType);
if (nScriptType == SvtScriptType::LATIN)
pNewSet->Put(SvxLanguageItem(nLangType,
pItemPool->GetWhichIDFromSlotID(SID_ATTR_CHAR_LANGUAGE)));
if (nScriptType == SvtScriptType::COMPLEX)
pNewSet->Put(SvxLanguageItem(nLangType,
pItemPool->GetWhichIDFromSlotID(SID_ATTR_CHAR_CTL_LANGUAGE)));
if (nScriptType == SvtScriptType::ASIAN)
pNewSet->Put(SvxLanguageItem(nLangType,
pItemPool->GetWhichIDFromSlotID(SID_ATTR_CHAR_CJK_LANGUAGE)));
}
pViewShell->ApplyAttributes(*pNewSet, rOldSet);
pBindings->Invalidate(SID_LANGUAGE_STATUS);
}
}
}
else if (bParagraph)
{
ScViewData* pViewData = GetViewData();
if (!pViewData)
return ;
EditView* pEditView = pViewData->GetEditView(pViewData->GetActivePart());
if (!pEditView)
return ;
const LanguageType nLangToUse = SvtLanguageTable::GetLanguageType( aLangText );
SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( nLangToUse );
SfxItemSet aAttrs = pEditView->getEditEngine().GetEmptyItemSet();
if (nScriptType == SvtScriptType::LATIN)
aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE ) );
if (nScriptType == SvtScriptType::COMPLEX)
aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE_CTL ) );
if (nScriptType == SvtScriptType::ASIAN)
aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE_CJK ) );
ESelection aOldSel;
if (bParagraph)
{
ESelection aSel = pEditView->GetSelection();
aOldSel = aSel;
aSel.start.nIndex = 0;
aSel.end.nIndex = EE_TEXTPOS_MAX;
pEditView->SetSelection( aSel );
}
pEditView->SetAttribs( aAttrs );
if (bParagraph)
pEditView->SetSelection( aOldSel );
}
else if ( eLang != eLatin )
{
if ( ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell() )
{
ScInputHandler* pInputHandler = ScModule::get()->GetInputHdl(pViewSh);
if ( pInputHandler )
pInputHandler->UpdateSpellSettings();
pViewSh->UpdateDrawTextOutliner();
}
SetDocumentModified();
Broadcast(SfxHint(SfxHintId::LanguageChanged));
PostPaintGridAll();
}
}
}
break ;
case SID_SPELLCHECK_IGNORE_ALL:
{
ScViewData* pViewData = GetViewData();
if (!pViewData)
return ;
EditView* pEditView = pViewData->GetEditView(pViewData->GetActivePart());
if (!pEditView)
return ;
OUString sIgnoreText;
const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
if (pItem2)
sIgnoreText = pItem2->GetValue();
if (sIgnoreText == "Spelling" )
{
ESelection aOldSel = pEditView->GetSelection();
pEditView->SpellIgnoreWord();
pEditView->SetSelection( aOldSel );
}
}
break ;
case SID_SPELLCHECK_APPLY_SUGGESTION:
{
ScViewData* pViewData = GetViewData();
if (!pViewData)
return ;
EditView* pEditView = pViewData->GetEditView(pViewData->GetActivePart());
if (!pEditView)
return ;
OUString sApplyText;
const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
if (pItem2)
sApplyText = pItem2->GetValue();
static constexpr OUString sSpellingRule(u"Spelling_" _ustr);
sal_Int32 nPos = 0;
if (-1 != (nPos = sApplyText.indexOf( sSpellingRule )))
{
sApplyText = sApplyText.replaceAt(nPos, sSpellingRule.getLength(), u"" );
pEditView->InsertText( sApplyText );
}
}
break ;
case SID_REFRESH_VIEW:
{
PostPaintGridAll();
}
break ;
case SID_PROTECTPOS:
case SID_PROTECTSIZE:
{
ScTabViewShell* pViewShell = GetBestViewShell();
if (!pViewShell)
return ;
ScDrawView* pScDrawView = pViewShell->GetViewData().GetScDrawView();
if (!pScDrawView)
return ;
const SdrMarkList& rMarkList = pScDrawView->GetMarkedObjectList();
assert ( rMarkList.GetMarkCount() == 1 );
SdrObject* pGraphicObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
if (nSlot == SID_PROTECTSIZE)
pGraphicObj->SetResizeProtect(!pGraphicObj->IsResizeProtect());
else
pGraphicObj->SetMoveProtect(!pGraphicObj->IsMoveProtect());
}
break ;
default :
{
// small (?) hack -> forwarding of the slots to TabViewShell
ScTabViewShell* pSh = GetBestViewShell();
if ( pSh )
pSh->Execute( rReq );
#if HAVE_FEATURE_SCRIPTING
else
SbxBase::SetError( ERRCODE_BASIC_NO_ACTIVE_OBJECT );
#endif
}
}
}
void UpdateAcceptChangesDialog()
{
// update "accept changes" dialog
//! notify all views
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
if ( pViewFrm && pViewFrm->HasChildWindow( FID_CHG_ACCEPT ) )
{
SfxChildWindow* pChild = pViewFrm->GetChildWindow( FID_CHG_ACCEPT );
if ( pChild )
static_cast <ScAcceptChgDlgWrapper*>(pChild)->ReInitDlg();
}
}
void ScDocShell::ExecuteChartSource(SfxRequest& rReq)
{
const SfxItemSet* pReqArgs = rReq.GetArgs();
sal_uInt16 nSlot = rReq.GetSlot();
bool bUndo (m_pDocument->IsUndoEnabled());
if (!pReqArgs)
{
OSL_FAIL("SID_CHART_SOURCE without arguments" );
return ;
}
ScDocument& rDoc = GetDocument();
const SfxPoolItem* pItem;
OUString aChartName, aRangeName;
ScRange aSingleRange;
ScRangeListRef aRangeListRef;
bool bMultiRange = false ;
bool bColHeaders = true ;
bool bRowHeaders = true ;
bool bColInit = false ;
bool bRowInit = false ;
bool bAddRange = (nSlot == SID_CHART_ADDSOURCE);
if ( const SfxStringItem* pChartItem = pReqArgs->GetItemIfSet( SID_CHART_NAME ) )
aChartName = pChartItem->GetValue();
if ( const SfxStringItem* pChartItem = pReqArgs->GetItemIfSet( SID_CHART_SOURCE ) )
aRangeName = pChartItem->GetValue();
if ( pReqArgs->HasItem( FN_PARAM_1, &pItem ) )
{
bColHeaders = static_cast <const SfxBoolItem*>(pItem)->GetValue();
bColInit = true ;
}
if ( pReqArgs->HasItem( FN_PARAM_2, &pItem ) )
{
bRowHeaders = static_cast <const SfxBoolItem*>(pItem)->GetValue();
bRowInit = true ;
}
ScAddress::Details aDetails(rDoc.GetAddressConvention(), 0, 0);
bool bValid = (aSingleRange.ParseAny(aRangeName, rDoc, aDetails) & ScRefFlags::VALID) != ScRefFlags::ZERO;
if (!bValid)
{
aRangeListRef = new ScRangeList;
aRangeListRef->Parse( aRangeName, rDoc, rDoc.GetAddressConvention());
if ( !aRangeListRef->empty() )
{
bMultiRange = true ;
aSingleRange = aRangeListRef->front(); // for header
bValid = true ;
}
else
aRangeListRef.clear();
}
ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
if (!pViewSh || !bValid || aChartName.isEmpty() )
{
OSL_FAIL("UpdateChartArea: no ViewShell or wrong data" );
rReq.Done();
return ;
}
weld::Window* pParent = pViewSh->GetFrameWeld();
SCCOL nCol1 = aSingleRange.aStart.Col();
SCROW nRow1 = aSingleRange.aStart.Row();
SCCOL nCol2 = aSingleRange.aEnd.Col();
SCROW nRow2 = aSingleRange.aEnd.Row();
SCTAB nTab = aSingleRange.aStart.Tab();
//! limit always or not at all ???
if (!bMultiRange)
m_pDocument->LimitChartArea( nTab, nCol1,nRow1, nCol2,nRow2 );
// Dialog for column/row headers
if ( !bAddRange && ( !bColInit || !bRowInit ) )
{
ScChartPositioner aChartPositioner( *m_pDocument, nTab, nCol1,nRow1, nCol2,nRow2 );
if (!bColInit)
bColHeaders = aChartPositioner.HasColHeaders();
if (!bRowInit)
bRowHeaders = aChartPositioner.HasRowHeaders();
auto xRequest = std::make_shared<SfxRequest>(rReq);
rReq.Ignore(); // the 'old' request is not relevant any more
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
VclPtr<AbstractScColRowLabelDlg> pDlg(pFact->CreateScColRowLabelDlg(pParent, bRowHeaders, bColHeaders));
pDlg->StartExecuteAsync(
[this , pDlg, xRequest=std::move(xRequest), bUndo, bMultiRange,
aChartName, aRangeListRef=std::move(aRangeListRef), bAddRange,
nCol1, nRow1, nCol2, nRow2, nTab] (sal_Int32 nResult)->void
{
if (nResult == RET_OK)
{
bool bColHeaders2 = pDlg->IsRow();
bool bRowHeaders2 = pDlg->IsCol();
xRequest->AppendItem(SfxBoolItem(FN_PARAM_1, bColHeaders2));
xRequest->AppendItem(SfxBoolItem(FN_PARAM_2, bRowHeaders2));
ExecuteChartSourcePost(bUndo, bMultiRange,
aChartName, aRangeListRef, bColHeaders2, bRowHeaders2, bAddRange,
nCol1, nRow1, nCol2, nRow2, nTab);
}
pDlg->disposeOnce();
xRequest->Done();
}
);
}
else
{
ExecuteChartSourcePost(bUndo, bMultiRange,
aChartName, aRangeListRef, bColHeaders, bRowHeaders, bAddRange,
nCol1, nRow1,nCol2, nRow2, nTab);
rReq.Done();
}
}
void ScDocShell::ExecuteChartSourcePost(bool bUndo, bool bMultiRange,
const OUString& rChartName, const ScRangeListRef& rRangeListRef,
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5 C=95 H=99 G=96
¤ Dauer der Verarbeitung: 0.21 Sekunden
¤
*© Formatika GbR, Deutschland