/* -*- 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 .
*/
usingnamespace com::sun::star; using ::com::sun::star::uno::Reference; using ::com::sun::star::lang::XMultiServiceFactory; using std::shared_ptr; using ::std::vector;
HiddenInformation ScDocShell::GetHiddenInformationState( HiddenInformation nStates )
{ // get global state like HiddenInformation::DOCUMENTVERSIONS
HiddenInformation nState = SfxObjectShell::GetHiddenInformationState( nStates );
// prevent unnecessary broadcasts and updates
OSL_ENSURE(m_pModificator == nullptr, "The Modificator should not exist");
m_pModificator.reset( new ScDocShellModificator( *this ) );
m_pDocument->SetImportingXML( true );
m_pDocument->EnableExecuteLink( false ); // #i101304# to be safe, prevent nested loading from external references
m_pDocument->EnableUndo( false ); // prevent unnecessary broadcasts and "half way listeners"
m_pDocument->SetInsertingFromOtherDoc( true );
}
void ScDocShell::AfterXMLLoading(bool bRet)
{ if (GetCreateMode() != SfxObjectCreateMode::ORGANIZER)
{
UpdateLinks(); // don't prevent establishing of listeners anymore
m_pDocument->SetInsertingFromOtherDoc( false ); if ( bRet )
{
ScChartListenerCollection* pChartListener = m_pDocument->GetChartListenerCollection(); if (pChartListener)
pChartListener->UpdateDirtyCharts();
// #95582#; set the table names of linked tables to the new path
SCTAB nTabCount = m_pDocument->GetTableCount(); for (SCTAB i = 0; i < nTabCount; ++i)
{ if (m_pDocument->IsLinked( i ))
{
OUString aName;
m_pDocument->GetName(i, aName);
OUString aLinkTabName = m_pDocument->GetLinkTab(i);
sal_Int32 nLinkTabNameLength = aLinkTabName.getLength();
sal_Int32 nNameLength = aName.getLength(); if (nLinkTabNameLength < nNameLength)
{
// remove the quotes on begin and end of the docname and restore the escaped quotes const sal_Unicode* pNameBuffer = aName.getStr(); if ( *pNameBuffer == '\'' && // all docnames have to have a ' character on the first pos
ScGlobal::UnicodeStrChr( pNameBuffer, SC_COMPILER_FILE_TAB_SEP ) )
{
OUStringBuffer aDocURLBuffer; bool bQuote = true; // Document name is always quoted
++pNameBuffer; while ( bQuote && *pNameBuffer )
{ if ( *pNameBuffer == '\'' && *(pNameBuffer-1) != '\\' )
bQuote = false; elseif( *pNameBuffer != '\\' || *(pNameBuffer+1) != '\'' )
aDocURLBuffer.append(*pNameBuffer); // If escaped quote: only quote in the name
++pNameBuffer;
}
if( *pNameBuffer == SC_COMPILER_FILE_TAB_SEP ) // after the last quote of the docname should be the # char
{
sal_Int32 nIndex = nNameLength - nLinkTabNameLength;
INetURLObject aINetURLObject(aDocURLBuffer); if(aName.match( aLinkTabName, nIndex) &&
(aName[nIndex - 1] == '#') && // before the table name should be the # char
!aINetURLObject.HasError()) // the docname should be a valid URL
{
aName = ScGlobal::GetDocTabName( m_pDocument->GetLinkDoc( i ), m_pDocument->GetLinkTab( i ) );
m_pDocument->RenameTab(i, aName, true/*bExternalDocument*/);
} // else; nothing has to happen, because it is a user given name
} // else; nothing has to happen, because it is a user given name
} // else; nothing has to happen, because it is a user given name
} // else; nothing has to happen, because it is a user given name
}
}
// #i94570# DataPilot table names have to be unique, or the tables can't be accessed by API. // If no name (or an invalid name, skipped in ScXMLDataPilotTableContext::EndElement) was set, create a new name.
ScDPCollection* pDPCollection = m_pDocument->GetDPCollection(); if ( pDPCollection )
{
size_t nDPCount = pDPCollection->GetCount(); for (size_t nDP=0; nDP<nDPCount; ++nDP)
{
ScDPObject& rDPObj = (*pDPCollection)[nDP]; if (rDPObj.GetName().isEmpty())
rDPObj.SetName( pDPCollection->CreateNewName() );
}
}
}
} else
m_pDocument->SetInsertingFromOtherDoc( false );
if (m_pModificator)
{
ScDocument::HardRecalcState eRecalcState = m_pDocument->GetHardRecalcState(); // Temporarily set hard-recalc to prevent calling // ScFormulaCell::Notify() during destruction of the Modificator which // will set the cells dirty. if (eRecalcState == ScDocument::HardRecalcState::OFF)
m_pDocument->SetHardRecalcState(ScDocument::HardRecalcState::TEMPORARY);
m_pModificator.reset();
m_pDocument->SetHardRecalcState(eRecalcState);
} else
{
OSL_FAIL("The Modificator should exist");
}
const sc::ImportPostProcessData::DataStream& r = *rData.mpDataStream; if (!r.maRange.IsValid()) return;
// Break the streamed range into the top range and the height limit. A // height limit of 0 means unlimited i.e. the streamed data will go all // the way to the last row.
bool bHardRecalc = false; switch (nRecalcMode)
{ case RECALC_ASK:
{ if (m_pDocument->IsUserInteractionEnabled())
{ // Ask if the user wants to perform full re-calculation.
MessageWithCheck aQueryBox(ScDocShell::GetActiveDialogParent(),
u"modules/scalc/ui/recalcquerydialog.ui"_ustr,
u"RecalcQueryDialog"_ustr);
aQueryBox.set_primary_text(ScResId(STR_QUERY_OPT_ROW_HEIGHT_RECALC_ONLOAD));
aQueryBox.set_default_response(RET_YES);
if (officecfg::Office::Calc::Formula::Load::RecalcOptimalRowHeightMode::isReadOnly())
aQueryBox.hide_ask();
bHardRecalc = aQueryBox.run() == RET_YES;
if (aQueryBox.get_active())
{ // Always perform selected action in the future.
std::shared_ptr<comphelper::ConfigurationChanges> batch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Calc::Formula::Load::RecalcOptimalRowHeightMode::set(
bHardRecalc ? static_cast<sal_Int32>(RECALC_ALWAYS)
: static_cast<sal_Int32>(RECALC_NEVER),
batch);
//if the document was not generated by LibreOffice, do hard recalc in case some other document //generator saved cached formula results that differ from LibreOffice's calculated results or //did not use cached formula results.
uno::Reference<document::XDocumentProperties> xDocProps = GetModel()->getDocumentProperties();
bool bHardRecalc = false; if (nRecalcMode == RECALC_ASK)
{
OUString sProductName(utl::ConfigManager::getProductName()); if (m_pDocument->IsUserInteractionEnabled() && xDocProps->getGenerator().indexOf(sProductName) == -1)
{ // Generator is not LibreOffice. Ask if the user wants to perform // full re-calculation.
MessageWithCheck aQueryBox(GetActiveDialogParent(),
u"modules/scalc/ui/recalcquerydialog.ui"_ustr, u"RecalcQueryDialog"_ustr);
aQueryBox.set_primary_text(ScResId(STR_QUERY_FORMULA_RECALC_ONLOAD_ODS));
aQueryBox.set_default_response(RET_YES);
if ( officecfg::Office::Calc::Formula::Load::OOXMLRecalcMode::isReadOnly() )
aQueryBox.hide_ask();
bHardRecalc = aQueryBox.run() == RET_YES;
if (aQueryBox.get_active())
{ // Always perform selected action in the future.
std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
officecfg::Office::Calc::Formula::Load::ODFRecalcMode::set(sal_Int32(0), batch);
ScModule* mod = ScModule::get();
ScFormulaOptions aOpt = mod->GetFormulaOptions();
aOpt.SetODFRecalcOptions(bHardRecalc ? RECALC_ALWAYS : RECALC_NEVER); /* XXX is this really supposed to set the ScModule options?
* Not the ScDocShell options? */
mod->SetFormulaOptions(aOpt);
if (bHardRecalc)
DoHardRecalc(); else
{ // still need to recalc volatile formula cells.
m_pDocument->Broadcast(ScHint(SfxHintId::ScDataChanged, BCA_BRDCST_ALWAYS));
}
// only the latin script language is loaded // -> initialize the others from options (before loading)
InitOptions(true);
// If this is an ODF file being loaded, then by default, use legacy processing // (if required, it will be overridden in *::ReadUserDataSequence()) if (IsOwnStorageFormat(rMedium))
{ if (ScDrawLayer* pDrawLayer = m_pDocument->GetDrawLayer())
{
pDrawLayer->SetCompatibilityFlag(SdrCompatibilityFlag::AnchoredTextOverflowLegacy, true); // for tdf#99729
pDrawLayer->SetCompatibilityFlag(SdrCompatibilityFlag::LegacyFontwork, true); // for tdf#148000
}
}
GetUndoManager()->Clear();
bool bRet = SfxObjectShell::Load(rMedium); if (bRet)
{
SetInitialLinkUpdate(&rMedium);
{ // prepare a valid document for XML filter // (for ConvertFrom, InitNew is called before)
m_pDocument->MakeTable(0);
m_pDocument->GetStyleSheetPool()->CreateStandardStyles();
m_pDocument->getCellAttributeHelper().UpdateAllStyleSheets(*m_pDocument);
/* Create styles that are imported through Orcus */
if ( bNoLockAccess )
{ // TODO/LATER: in future an error regarding impossibility to open file for writing could be shown
ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
} else
{
OUString aMessage( ScResId( STR_FILE_LOCKED_SAVE_LATER ) );
aMessage = aMessage.replaceFirst( "%1", aUserName );
// store to shared file if ( bSaveToShared )
{ bool bChangedViewSettings = false;
ScChangeViewSettings* pChangeViewSet = m_pDocument->GetChangeViewSettings(); if ( pChangeViewSet && pChangeViewSet->ShowChanges() )
{
pChangeViewSet->SetShowChanges( false );
pChangeViewSet->SetShowAccepted( false );
m_pDocument->SetChangeViewSettings( *pChangeViewSet );
bChangedViewSettings = true;
}
// TODO/LATER: More entries from the MediaDescriptor might be interesting for the merge
uno::Sequence< beans::PropertyValue > aValues{
comphelper::makePropertyValue(
u"FilterName"_ustr,
GetMedium()->GetFilter()->GetFilterName())
};
if ( bEntriesNotAccessible )
{ // TODO/LATER: in future an error regarding impossibility to write to share control file could be shown
ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
} else
{
std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetActiveDialogParent(),
VclMessageType::Warning, VclButtonsType::Ok,
ScResId(STR_DOC_NOLONGERSHARED)));
xWarn->run();
if ( !bSuccess )
SetError(ERRCODE_IO_ABORT); // this error code will produce no error message, but will break the further saving process
} #endif
if (m_pSheetSaveData)
m_pSheetSaveData->SetInSupportedSave(true);
} break; case SfxEventHintId::SaveAsDoc:
{ if ( GetDocument().GetExternalRefManager()->containsUnsavedReferences() )
{
std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetActiveDialogParent(),
VclMessageType::Warning, VclButtonsType::YesNo,
ScResId(STR_UNSAVED_EXT_REF))); if (RET_NO == xWarn->run())
{
SetError(ERRCODE_IO_ABORT); // this error code will produce no error message, but will break the further saving process
}
}
[[fallthrough]];
} case SfxEventHintId::SaveToDoc: // #i108978# If no event is sent before saving, there will also be no "...DONE" event, // and SAVE/SAVEAS can't be distinguished from SAVETO. So stream copying is only enabled // if there is a SAVE/SAVEAS/SAVETO event first. if (m_pSheetSaveData)
m_pSheetSaveData->SetInSupportedSave(true); break; case SfxEventHintId::SaveDocDone: case SfxEventHintId::SaveAsDocDone:
{ // new positions are used after "save" and "save as", but not "save to"
UseSheetSaveEntries(); // use positions from saved file for next saving
[[fallthrough]];
} case SfxEventHintId::SaveToDocDone: // only reset the flag, don't use the new positions if (m_pSheetSaveData)
m_pSheetSaveData->SetInSupportedSave(false); break; default:
{
} break;
}
} elseif (rHint.GetId() == SfxHintId::TitleChanged) // Without parameter
{
m_pDocument->SetName( SfxShell::GetName() ); // RegisterNewTargetNames doesn't exist any longer
SfxGetpApp()->Broadcast(SfxHint( SfxHintId::ScDocNameChanged )); // Navigator
} elseif (rHint.GetId() == SfxHintId::Deinitializing)
{
if (m_pDocument->IsClipboardSource())
{ // Notes copied to the clipboard have a raw SdrCaptionObj pointer // copied from this document, forget it as it references this // document's drawing layer pages and what not, which otherwise when // pasting to another document after this document was destructed would // attempt to access non-existing data. Preserve the text data though.
ScDocument* pClipDoc = ScModule::GetClipDoc(); if (pClipDoc)
pClipDoc->ClosingClipboardSource();
}
}
if (rHint.GetId() != SfxHintId::ThisIsAnSfxEventHint) return;
// All filters need the complete file in one piece (not asynchronously) // So make sure that we transfer the whole file with CreateFileStream
rMedium.GetPhysicalName(); //! Call CreateFileStream directly, if available
MakeDrawLayer(); //! In the filter
CalcOutputFactor(); // prepare update of row height
ErrCode eError = ScFormatFilter::Get().ScImportExcel( rMedium, m_pDocument.get(), eFormat );
m_pDocument->UpdateFontCharSet(); if ( m_pDocument->IsChartListenerCollectionNeedsUpdate() )
m_pDocument->UpdateChartListenerCollection(); //! For all imports?
// all graphics objects must have names
m_pDocument->EnsureGraphicNames();
// tdf#82254 - check whether to include a byte-order-mark in the output if (constbool bIncludeBOM = aImpEx.GetIncludeBOM())
{
aOptions.SetIncludeBOM(bIncludeBOM);
rMedium.GetItemSet().Put(
SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions.WriteToString()));
}
// for mobile case, we use a copy of the original document and give it a temporary name before editing // Therefore, the sheet name becomes ugly, long and nonsensical. #if !(defined ANDROID) // The same resulting name has to be handled in // ScExternalRefCache::initializeDoc() and related, hence // pass 'true' for RenameTab()'s bExternalDocument for a // composed name so ValidTabName() will not be checked, // which could veto the rename in case it contained // characters that Excel does not handle. If we wanted to // change that then it needed to be handled in all // corresponding places of the external references // manager/cache. Likely then we'd also need a method to // compose a name excluding such characters.
m_pDocument->RenameTab( 0, INetURLObject( rMedium.GetName()).GetBase(), true/*bExternalDocument*/); #endif
bOverflowRow = aImpEx.IsOverflowRow();
bOverflowCol = aImpEx.IsOverflowCol();
bOverflowCell = aImpEx.IsOverflowCell();
} else
{
OSL_FAIL( "No Stream" );
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.