xComponent = aEnv.getTargetComponent();
} catch(const LoadEnvException& ex)
{ switch(ex.m_nID)
{ case LoadEnvException::ID_INVALID_MEDIADESCRIPTOR: throw css::lang::IllegalArgumentException(
u"Optional list of arguments seem to be corrupted."_ustr, xLoader, 4);
// if AbortOnLoadFailure is set and we couldn't load the document, assert, intended for use with crashtesting to // detect when we export something we can't import
assert(xComponent.is() || comphelper::NamedValueCollection::get(lArgs, u"AbortOnLoadFailure") != uno::Any(true));
// Handle still running processes! if (m_xAsynchronousJob.is()) throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
// take over all new parameters.
m_xTargetFrame.clear();
m_xBaseFrame = xBaseFrame;
m_lMediaDescriptor = addModelArgs(lMediaDescriptor);
m_sTarget = sTarget;
m_nSearchFlags = nSearchFlags;
m_eFeature = eFeature;
m_eContentType = E_UNSUPPORTED_CONTENT;
m_bCloseFrameOnError = false;
m_bReactivateControllerOnError = false;
m_bLoaded = false;
OUString aRealURL; if (!officecfg::Office::Common::Load::DetectWebDAVRedirection::get()
|| !tools::IsMappedWebDAVPath(sURL, &aRealURL))
aRealURL = sURL;
// try to find out, if it's really a content, which can be loaded or must be "handled" // We use a default value for this in-parameter. Then we have to start a complex check method // internally. But if this check was already done outside it can be suppressed to perform // the load request. We take over the result then!
m_eContentType = LoadEnv::classifyContent(aRealURL, lMediaDescriptor); if (m_eContentType == E_UNSUPPORTED_CONTENT) throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT, u"from LoadEnv::startLoading"_ustr);
// make URL part of the MediaDescriptor // It doesn't matter if it is already an item of it. // It must be the same value... so we can overwrite it :-)
m_lMediaDescriptor[utl::MediaDescriptor::PROP_URL] <<= aRealURL;
// parse it - because some following code require that
m_aURL.Complete = aRealURL;
uno::Reference<util::XURLTransformer> xParser(util::URLTransformer::create(m_xContext));
xParser->parseStrict(m_aURL);
// BTW: Split URL and JumpMark ... // Because such mark is an explicit value of the media descriptor! if (!m_aURL.Mark.isEmpty())
m_lMediaDescriptor[utl::MediaDescriptor::PROP_JUMPMARK] <<= m_aURL.Mark;
// By the way: remove the old and deprecated value "FileName" from the descriptor!
utl::MediaDescriptor::iterator pIt = m_lMediaDescriptor.find(utl::MediaDescriptor::PROP_FILENAME); if (pIt != m_lMediaDescriptor.end())
m_lMediaDescriptor.erase(pIt);
// patch the MediaDescriptor, so it fulfil the outside requirements // Means especially items like e.g. UI InteractionHandler, Status Indicator, // MacroExecutionMode, etc.
/*TODO progress is bound to a frame ... How can we set it here? */
if ( i_bUIMode )
{
nMacroMode = css::document::MacroExecMode::USE_CONFIG;
nUpdateMode = css::document::UpdateDocMode::ACCORDING_TO_CONFIG; try
{ // tdf#154308 At least for the case the document is launched from the StartCenter, put that StartCenter as the // parent for any dialogs that may appear during typedetection (once load starts a permanent frame will be set // anyway and used as dialog parent, which will be this one if the startcenter was running)
css::uno::Reference<css::frame::XFramesSupplier> xSupplier = css::frame::Desktop::create(i_rxContext);
FrameListAnalyzer aTasksAnalyzer(xSupplier, css::uno::Reference<css::frame::XFrame>(), FrameAnalyzerFlags::BackingComponent);
css::uno::Reference<css::awt::XWindow> xDialogParent(aTasksAnalyzer.m_xBackingComponent ?
aTasksAnalyzer.m_xBackingComponent->getContainerWindow() :
nullptr);
// Handle still running processes! if (m_xAsynchronousJob.is()) throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
// content can not be loaded or handled // check "classifyContent()" failed before ... if (m_eContentType == E_UNSUPPORTED_CONTENT) throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT,
u"from LoadEnv::start"_ustr);
} // <- SAFE
// detect its type/filter etc. // This information will be available by the // used descriptor member afterwards and is needed // for all following operations! // Note: An exception will be thrown, in case operation was not successfully ... if (m_eContentType != E_CAN_BE_SET)/* Attention: special feature to set existing component on a frame must ignore type detection! */
impl_detectTypeAndFilter();
// start loading the content... // Attention: Don't check m_eContentType deeper then UNSUPPORTED/SUPPORTED! // Because it was made in the easiest way... may a flat detection was made only. // And such simple detection can fail sometimes .-) // Use another strategy here. Try it and let it run into the case "loading not possible". bool bStarted = false; if (
(m_eFeature & LoadEnvFeatures::AllowContentHandler) &&
(m_eContentType != E_CAN_BE_SET ) /* Attention: special feature to set existing component on a frame must ignore type detection! */
)
{
bStarted = impl_handleContent();
}
if (!bStarted)
bStarted = impl_loadContent();
// not started => general error // We can't say - what was the reason for. if (!bStarted) throw LoadEnvException(
LoadEnvException::ID_GENERAL_ERROR, u"not started"_ustr);
}
/*----------------------------------------------- TODO Firstdraftdoesnotimplementtimeoutusing[ms]. Currentimplementationcountsyieldcallsonly...
-----------------------------------------------*/ bool LoadEnv::waitWhileLoading(sal_uInt32 nTimeout)
{ // Because it's not a good idea to block the main thread // (and we can't be sure that we are currently not used inside the // main thread!), we can't use conditions here really. We must yield // in an intelligent manner :-)
// clearing of this reference will unblock waitWhileLoading()! // So we must be sure, that loading process was really finished. // => do it as last operation of this method ...
m_xAsynchronousJob.clear();
}
// (i) Filter some special well known URL protocols, // which can not be handled or loaded in general. // Of course an empty URL must be ignored here too. // Note: These URL schemata are fix and well known ... // But there can be some additional ones, which was not // defined at implementation time of this class :-( // So we have to make sure, that the following code // can detect such protocol schemata too :-)
// (ii) Some special URLs indicates a given input stream, // a full featured document model directly or // specify a request for opening an empty document. // Such contents are loadable in general. // But we have to check, if the media descriptor contains // all needed resources. If they are missing - the following // load request will fail.
/* Attention: The following code can't work on such special URLs! Itshouldnotbreaktheoffice...butitmakesnosense tostartexpensiveobjectcreationsandcomplexsearch algorithmifit'sclear,thatsuchURLsmustbehandled inaspecialway.-)
*/
// creation of new documents if (ProtocolCheck::isProtocol(sURL,EProtocol::PrivateFactory)) return E_CAN_BE_LOADED;
// using of an existing input stream
utl::MediaDescriptor stlMediaDescriptor(lMediaDescriptor);
utl::MediaDescriptor::const_iterator pIt; if (ProtocolCheck::isProtocol(sURL,EProtocol::PrivateStream))
{
pIt = stlMediaDescriptor.find(utl::MediaDescriptor::PROP_INPUTSTREAM);
css::uno::Reference< css::io::XInputStream > xStream; if (pIt != stlMediaDescriptor.end())
pIt->second >>= xStream; if (xStream.is()) return E_CAN_BE_LOADED;
SAL_INFO("fwk.loadenv", "LoadEnv::classifyContent(): loading from stream with right URL but invalid stream detected"); return E_UNSUPPORTED_CONTENT;
}
// using of a full featured document if (ProtocolCheck::isProtocol(sURL,EProtocol::PrivateObject))
{
pIt = stlMediaDescriptor.find(utl::MediaDescriptor::PROP_MODEL);
css::uno::Reference< css::frame::XModel > xModel; if (pIt != stlMediaDescriptor.end())
pIt->second >>= xModel; if (xModel.is()) return E_CAN_BE_SET;
SAL_INFO("fwk.loadenv", "LoadEnv::classifyContent(): loading with object with right URL but invalid object detected"); return E_UNSUPPORTED_CONTENT;
}
// following operations can work on an internal type name only :-( const css::uno::Reference< css::uno::XComponentContext >& xContext = ::comphelper::getProcessComponentContext();
css::uno::Reference< css::document::XTypeDetection > xDetect(
xContext->getServiceManager()->createInstanceWithContext(
u"com.sun.star.document.TypeDetection"_ustr, xContext),
css::uno::UNO_QUERY_THROW);
// (iii) If a FrameLoader service (or at least // a Filter) can be found, which supports // this URL - it must be a loadable content. // Because both items are registered for types // it's enough to check for frame loaders only. // Most of our filters are handled by our global // default loader. But there exist some specialized // loader, which does not work on top of filters! // So it's not enough to search on the filter configuration. // Further it's not enough to search for types! // Because there exist some types, which are referenced by // other objects... but neither by filters nor frame loaders!
css::uno::Sequence< OUString > lTypesReg { sType };
css::uno::Sequence< css::beans::NamedValue > lQuery
{
css::beans::NamedValue(PROP_TYPES, css::uno::Any(lTypesReg))
};
xLoaderFactory = css::frame::FrameLoaderFactory::create(xContext);
xSet = xLoaderFactory->createSubSetEnumerationByProperties(lQuery); // at least one registered frame loader is enough! if (xSet->hasMoreElements()) return E_CAN_BE_LOADED;
// (iv) Some URL protocols are supported by special services. // E.g. ContentHandler. // Such contents can be handled ... but not loaded.
xLoaderFactory = css::frame::ContentHandlerFactory::create(xContext);
xSet = xLoaderFactory->createSubSetEnumerationByProperties(lQuery); // at least one registered content handler is enough! if (xSet->hasMoreElements()) return E_CAN_BE_HANDLED;
// (v) Last but not least the UCB is used inside office to // load contents. He has a special configuration to know // which URL schemata can be used inside office.
css::uno::Reference< css::ucb::XUniversalContentBroker > xUCB(css::ucb::UniversalContentBroker::create(xContext)); if (xUCB->queryContentProvider(sURL).is()) return E_CAN_BE_LOADED;
// (TODO) At this point, we have no idea .-) // But it seems to be better, to break all // further requests for this URL. Otherwise // we can run into some trouble. return E_UNSUPPORTED_CONTENT;
}
// Attention: Because our stl media descriptor is a copy of a uno sequence // we can't use as an in/out parameter here. Copy it before and don't forget to // update structure afterwards again!
css::uno::Sequence< css::beans::PropertyValue > lDescriptor = m_lMediaDescriptor.getAsConstPropertyValueList();
css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
// Orcus type detected. Skip the normal type detection process.
m_lMediaDescriptor << lDescriptor;
m_lMediaDescriptor[utl::MediaDescriptor::PROP_TYPENAME] <<= sType;
m_lMediaDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= sFilter;
m_lMediaDescriptor[utl::MediaDescriptor::PROP_FILTERPROVIDER] <<= u"orcus"_ustr;
m_lMediaDescriptor[utl::MediaDescriptor::PROP_DOCUMENTSERVICE] <<= u"com.sun.star.sheet.SpreadsheetDocument"_ustr; return; // <- SAFE
}
css::uno::Reference< css::document::XTypeDetection > xDetect(
xContext->getServiceManager()->createInstanceWithContext(
u"com.sun.star.document.TypeDetection"_ustr, xContext),
css::uno::UNO_QUERY_THROW);
sType = xDetect->queryTypeByDescriptor(lDescriptor, true); /*TODO should deep detection be able for enable/disable it from outside? */
// no valid content -> loading not possible if (sType.isEmpty()) throw LoadEnvException(
LoadEnvException::ID_UNSUPPORTED_CONTENT, u"type detection failed"_ustr);
// detection was successful => update the descriptor member of this class
m_lMediaDescriptor << lDescriptor;
m_lMediaDescriptor[utl::MediaDescriptor::PROP_TYPENAME] <<= sType; // Is there an already detected (may be preselected) filter? // see below ...
sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_FILTERNAME, OUString());
aWriteLock.clear(); // <- SAFE
// We do have potentially correct type, but the detection process was aborted. if (m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_ABORTED, false)) throw LoadEnvException(
LoadEnvException::ID_UNSUPPORTED_CONTENT, u"type detection aborted"_ustr);
// But the type isn't enough. For loading sometimes we need more information. // E.g. for our "_default" feature, where we recycle any frame which contains // and "Untitled" document, we must know if the new document is based on a template! // But this information is available as a filter property only. // => We must try(!) to detect the right filter for this load request. // On the other side ... if no filter is available .. ignore it. // Then the type information must be enough. if (sFilter.isEmpty())
{ // no -> try to find a preferred filter for the detected type. // Don't forget to update the media descriptor.
css::uno::Reference< css::container::XNameAccess > xTypeCont(xDetect, css::uno::UNO_QUERY_THROW); try
{
::comphelper::SequenceAsHashMap lTypeProps(xTypeCont->getByName(sType));
sFilter = lTypeProps.getUnpackedValueOrDefault(u"PreferredFilter"_ustr, OUString()); if (!sFilter.isEmpty())
{ // SAFE ->
aWriteLock.reset();
m_lMediaDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= sFilter;
aWriteLock.clear(); // <- SAFE
}
} catch(const css::container::NoSuchElementException&)
{}
}
// check if the filter (if one exists) points to a template format filter. // Then we have to add the property "AsTemplate". // We need this information to decide afterwards if we can use a "recycle frame" // for target "_default" or has to create a new one every time. // On the other side we have to suppress that, if this property already exists // and should trigger a special handling. Then the outside call of this method here, // has to know, what he is doing .-)
// the type must exist inside the descriptor ... otherwise this class is implemented wrong :-)
OUString sType = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_TYPENAME, OUString()); if (sType.isEmpty()) throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR);
// convert media descriptor and URL to right format for later interface call!
css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
m_lMediaDescriptor >> lDescriptor;
css::util::URL aURL = m_aURL;
// get necessary container to query for a handler object
css::uno::Reference< css::frame::XLoaderFactory > xLoaderFactory = css::frame::ContentHandlerFactory::create(m_xContext);
if (xInteraction.is())
{
css::uno::Any aInteraction;
rtl::Reference<comphelper::OInteractionAbort> pAbort = new comphelper::OInteractionAbort();
rtl::Reference<comphelper::OInteractionApprove> pApprove = new comphelper::OInteractionApprove();
// If we couldn't find a valid frame or the frame has no container window // we have to throw an exception. if (
( ! m_xTargetFrame.is() ) ||
( ! m_xTargetFrame->getContainerWindow().is() )
) throw LoadEnvException(LoadEnvException::ID_NO_TARGET_FOUND);
// Now we have a valid frame ... and type detection was already done. // We should apply the module dependent window position and size to the // frame window.
impl_applyPersistentWindowState(xTargetFrame->getContainerWindow());
// Don't forget to lock task for following load process. Otherwise it could die // during this operation runs by terminating the office or closing this task via api. // If we set this lock "close()" will return false and closing will be broken. // Attention: Don't forget to reset this lock again after finishing operation. // Otherwise task AND office couldn't die!!! // This includes gracefully handling of Exceptions (Runtime!) too ... // That's why we use a specialized guard, which will reset the lock // if it will be run out of scope.
// Note further: ignore if this internal guard already contains a resource. // Might impl_searchRecycleTarget() set it before. But in case this impl-method wasn't used // and the target frame was new created ... this lock here must be set!
css::uno::Reference< css::document::XActionLockable > xTargetLock(xTargetFrame, css::uno::UNO_QUERY);
m_aTargetLock.setResource(xTargetLock);
// Add status indicator to descriptor. Loader can show a progress then. // But don't do it, if loading should be hidden or preview is used...! // So we prevent our code against wrong using. Why? // It could be, that using of this progress could make trouble. e.g. He makes window visible... // but shouldn't do that. But if no indicator is available... nobody has a chance to do that! bool bHidden = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false); bool bMinimized = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_MINIMIZED, false); bool bPreview = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_PREVIEW, false); bool bStartPres = m_lMediaDescriptor.contains("StartPresentation");
if (!bHidden && !bMinimized && !bPreview && !bStartPres)
{
css::uno::Reference<css::task::XStatusIndicator> xProgress = m_lMediaDescriptor.getUnpackedValueOrDefault(
utl::MediaDescriptor::PROP_STATUSINDICATOR, css::uno::Reference<css::task::XStatusIndicator>()); if (!xProgress.is())
{ // Note: it's an optional interface!
css::uno::Reference< css::task::XStatusIndicatorFactory > xProgressFactory(xTargetFrame, css::uno::UNO_QUERY); if (xProgressFactory.is())
{
xProgress = xProgressFactory->createStatusIndicator(); if (xProgress.is())
m_lMediaDescriptor[utl::MediaDescriptor::PROP_STATUSINDICATOR] <<= xProgress;
}
}
// Now that we have a target window into which we can load, reinit the interaction handler to have this // window as its parent for modal dialogs and ensure the window is visible
css::uno::Reference< css::task::XInteractionHandler > xInteraction = m_lMediaDescriptor.getUnpackedValueOrDefault(
utl::MediaDescriptor::PROP_INTERACTIONHANDLER,
css::uno::Reference< css::task::XInteractionHandler >());
css::uno::Reference<css::lang::XInitialization> xHandler(xInteraction, css::uno::UNO_QUERY); if (xHandler.is())
{
css::uno::Reference<css::awt::XWindow> xWindow = xTargetFrame->getContainerWindow();
uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
{
{"Parent", uno::Any(xWindow)}
}));
xHandler->initialize(aArguments); //show the frame as early as possible to make it the parent of any message dialogs if (!impl_filterHasInteractiveDialog())
{
impl_makeFrameWindowVisible(xWindow, shouldFocusAndToFront());
m_bFocusedAndToFront = true; // no need to ask shouldFocusAndToFront second time
}
}
}
// convert media descriptor and URL to right format for later interface call!
css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
m_lMediaDescriptor >> lDescriptor;
OUString sURL = m_aURL.Complete;
returntrue;
} elseif (xSyncLoader.is())
{
uno::Reference<beans::XPropertySet> xTargetFrameProps(xTargetFrame, uno::UNO_QUERY); if (xTargetFrameProps.is())
{ // Set the URL on the frame itself, for the duration of the load, when it has no // controller.
xTargetFrameProps->setPropertyValue(u"URL"_ustr, uno::Any(sURL));
} bool bResult = xSyncLoader->load(lDescriptor, xTargetFrame); // react for the result here, so the outside waiting // code can ask for it later.
impl_setResult(bResult); // But the return value indicates a valid started(!) operation. // And that's true every time we reach this line :-) returntrue;
}
// special mode to set an existing component on this frame // In such case the loader is fix. It must be the SFX based implementation, // which can create a view on top of such xModel components :-) if (m_eContentType == E_CAN_BE_SET)
{ try
{ return css::frame::OfficeFrameLoader::create(m_xContext);
} catch(const css::uno::RuntimeException&)
{ throw; } catch(const css::uno::Exception&)
{} throw LoadEnvException(LoadEnvException::ID_INVALID_ENVIRONMENT);
}
// Otherwise... // We need this type information to locate a registered frame loader // Without such information we can't work!
OUString sType = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_TYPENAME, OUString()); if (sType.isEmpty()) throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR);
// try to locate any interested frame loader
css::uno::Reference< css::frame::XLoaderFactory > xLoaderFactory = css::frame::FrameLoaderFactory::create(m_xContext);
// such search is allowed for special requests only ... // or better it's not allowed for some requests in general :-) if (
( ! TargetHelper::matchSpecialTarget(m_sTarget, TargetHelper::ESpecialTarget::Default) ) ||
m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_ASTEMPLATE , false) || // (m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN() , false) == sal_True) ||
m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_OPENNEWVIEW, false)
)
{ return css::uno::Reference< css::frame::XFrame >();
}
// check URL // May it's not useful to start expensive document search, if it // can fail only .. because we load from a stream or model directly! if (
(ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateStream )) ||
(ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateObject )) /*TODO should be private:factory here tested too? */
)
{ return css::uno::Reference< css::frame::XFrame >();
}
// otherwise - iterate through the tasks of the desktop container // to find out, which of them might contains the requested document
css::uno::Reference< css::frame::XDesktop2 > xSupplier = css::frame::Desktop::create( m_xContext );
css::uno::Reference< css::container::XIndexAccess > xTaskList = xSupplier->getFrames();
if (!xTaskList.is()) return css::uno::Reference< css::frame::XFrame >(); // task list can be empty!
// Note: To detect if a document was already loaded before // we check URLs here only. But might the existing and the required // document has different versions! Then its URLs are the same...
sal_Int16 nNewVersion = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_VERSION, sal_Int16(-1));
// will be used to save the first hidden frame referring the searched model // Normally we are interested on visible frames... but if there is no such visible // frame we refer to any hidden frame also (but as fallback only).
css::uno::Reference< css::frame::XFrame > xHiddenTask;
css::uno::Reference< css::frame::XFrame > xTask;
sal_Int32 count = xTaskList->getCount(); for (sal_Int32 i=0; i<count; ++i)
{ try
{ // locate model of task // Note: Without a model there is no chance to decide if // this task contains the searched document or not!
xTaskList->getByIndex(i) >>= xTask; if (!xTask.is()) continue;
OUString sURL;
css::uno::Reference< css::frame::XController > xController = xTask->getController(); if (!xController.is())
{ // If we have no controller, then perhaps there is a load in progress. The frame // itself has the URL in this case.
uno::Reference<beans::XPropertySet> xTaskProps(xTask, uno::UNO_QUERY); if (xTaskProps.is())
{
xTaskProps->getPropertyValue(u"URL"_ustr) >>= sURL;
} if (sURL.isEmpty())
{
xTask.clear(); continue;
}
}
uno::Reference<frame::XModel> xModel; if (sURL.isEmpty())
{
xModel = xController->getModel(); if (!xModel.is())
{
xTask.clear(); continue;
}
// don't check the complete URL here. // use its main part - ignore optional jumpmarks!
sURL = xModel->getURL();
} if (!::utl::UCBContentHelper::EqualURLs( m_aURL.Main, sURL ))
{
xTask.clear (); continue;
}
// get the original load arguments from the current document // and decide if it's really the same then the one will be. // It must be visible and must use the same file revision ... // or must not have any file revision set (-1 == -1!)
utl::MediaDescriptor lOldDocDescriptor; if (xModel.is())
{
lOldDocDescriptor = xModel->getArgs();
// Hidden frames are special. // They will be used as "last chance" if there is no visible frame pointing to the same model. // Safe the result but continue with current loop might be looking for other visible frames. bool bIsHidden = lOldDocDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false); if ( bIsHidden && ! xHiddenTask.is() )
{
xHiddenTask = xTask;
xTask.clear (); continue;
}
// We found a visible task pointing to the right model ... // Break search. break;
} catch(const css::uno::RuntimeException&)
{ throw; } catch(const css::uno::Exception&)
{ continue; }
}
if (xResult.is())
{ // Now we are sure, that this task includes the searched document. // It's time to activate it. As special feature we try to jump internally // if an optional jumpmark is given too. if (!m_aURL.Mark.isEmpty())
impl_jumpToMark(xResult, m_aURL);
}
// ? no lock interface ? // Maybe it's an external written frame implementation :-( // Allowing using of it... but it can fail if it's not synchronized with our processes! if (!xLock.is()) returnfalse;
// Otherwise we have to look for any other existing lock. return xLock->isActionLocked();
}
// The special backing mode frame will be recycled by definition! // It doesn't matter if somewhere wants to create a new view // or open a new untitled document... // The only exception from that - hidden frames! if (m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false)) return css::uno::Reference< css::frame::XFrame >();
// These states indicates a wish for creation of a new view in general. if (
m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_ASTEMPLATE , false) ||
m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_OPENNEWVIEW, false)
)
{ return css::uno::Reference< css::frame::XFrame >();
}
// On the other side some special URLs will open a new frame every time (expecting // they can use the backing-mode frame!) if (
(ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateFactory )) ||
(ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateStream )) ||
(ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateObject ))
)
{ return css::uno::Reference< css::frame::XFrame >();
}
// No backing frame! No special URL => recycle active task - if possible. // Means - if it does not already contains a modified document, or // use another office module.
css::uno::Reference< css::frame::XFrame > xTask = xSupplier->getActiveFrame();
// not a real error - but might a focus problem! if (!xTask.is()) return css::uno::Reference< css::frame::XFrame >();
// not a real error - may it's a view only
css::uno::Reference< css::frame::XController > xController = xTask->getController(); if (!xController.is()) return css::uno::Reference< css::frame::XFrame >();
// not a real error - may it's a db component instead of a full featured office document
css::uno::Reference< css::frame::XModel > xModel = xController->getModel(); if (!xModel.is()) return css::uno::Reference< css::frame::XFrame >();
// get some more information ...
// A valid set URL means: there is already a location for this document. // => it was saved there or opened from there. Such Documents can not be used here. // We search for empty document ... created by a private:factory/ URL! if (xModel->getURL().getLength()>0) return css::uno::Reference< css::frame::XFrame >();
// The old document must be unmodified ...
css::uno::Reference< css::util::XModifiable > xModified(xModel, css::uno::UNO_QUERY); if (xModified->isModified()) return css::uno::Reference< css::frame::XFrame >();
// find out the application type of this document // We can recycle only documents, which uses the same application // then the new one.
SvtModuleOptions::EFactory eOldApp = SvtModuleOptions::ClassifyFactoryByModel(xModel);
SvtModuleOptions::EFactory eNewApp = SvtModuleOptions::ClassifyFactoryByURL (m_aURL.Complete, m_lMediaDescriptor.getAsConstPropertyValueList());
if (eOldApp != eNewApp) return css::uno::Reference< css::frame::XFrame >();
// OK this task seems to be usable for recycling // But we should mark it as such - means set an action lock. // Otherwise it would be used more than ones or will be destroyed // by a close() or terminate() request. // But if such lock already exist ... it means this task is used for // any other operation already. Don't use it then. if (impl_isFrameAlreadyUsedForLoading(xTask)) return css::uno::Reference< css::frame::XFrame >();
// OK - there is a valid target frame. // But may be it contains already a document. // Then we have to ask it, if it allows recycling of this frame .-) bool bReactivateOldControllerOnError = false;
css::uno::Reference< css::frame::XController > xOldDoc = xTask->getController(); if (xOldDoc.is())
{
utl::MediaDescriptor lOldDocDescriptor(xModel->getArgs());
// replaceable document if (!lOldDocDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_REPLACEABLE, false)) return css::uno::Reference< css::frame::XFrame >();
if (m_bLoaded)
{ // Bring the new loaded document to front (if allowed!). // Note: We show new created frames here only. // We don't hide already visible frames here ...
css::uno::Reference< css::awt::XWindow > xWindow = m_xTargetFrame->getContainerWindow(); bool bHidden = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false); bool bMinimized = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_MINIMIZED, false); bool bStartPres = m_lMediaDescriptor.contains("StartPresentation");
if (bMinimized)
{
SolarMutexGuard aSolarGuard; // check for system window is necessary to guarantee correct pointer cast! if (pWindow && pWindow->IsSystemWindow()) static_cast<WorkWindow*>(pWindow.get())->Minimize();
} elseif (!bHidden && !bStartPres)
{ // show frame ... if it's not still visible ... // But do nothing if it's already visible!
impl_makeFrameWindowVisible(xWindow, !m_bFocusedAndToFront && shouldFocusAndToFront());
}
if (pWindow)
pWindow->FlashWindow();
// Note: Only if an existing property "FrameName" is given by this media descriptor, // it should be used. Otherwise we should do nothing. May be the outside code has already // set a frame name on the target!
utl::MediaDescriptor::const_iterator pFrameName = m_lMediaDescriptor.find(utl::MediaDescriptor::PROP_FRAMENAME); if (pFrameName != m_lMediaDescriptor.end())
{
OUString sFrameName;
pFrameName->second >>= sFrameName; // Check the name again. e.g. "_default" isn't allowed. // On the other side "_beamer" is a valid name :-) if (TargetHelper::isValidNameForFrame(sFrameName))
m_xTargetFrame->setName(sFrameName);
}
} elseif (m_bReactivateControllerOnError)
{ // Try to reactivate the old document (if any exists!)
css::uno::Reference< css::frame::XController > xOldDoc = m_xTargetFrame->getController(); // clear does not depend from reactivation state of a might existing old document! // We must make sure, that a might following getTargetComponent() call does not return // the old document!
m_xTargetFrame.clear(); if (xOldDoc.is())
{ bool bReactivated = xOldDoc->suspend(false); if (!bReactivated) throw LoadEnvException(LoadEnvException::ID_COULD_NOT_REACTIVATE_CONTROLLER);
m_bReactivateControllerOnError = false;
}
} elseif (m_bCloseFrameOnError)
{ // close empty frames
css::uno::Reference< css::util::XCloseable > xCloseable (m_xTargetFrame, css::uno::UNO_QUERY);
// This max force an implicit closing of our target frame ... // e.g. in case close(sal_True) was called before and the frame // kill itself if our external use-lock is released here! // That's why we release this lock AFTER ALL OPERATIONS on this frame // are finished. The frame itself must handle then // this situation gracefully.
m_aTargetLock.freeResource();
// Last but not least :-) // We have to clear the current media descriptor. // Otherwise it hold a might existing stream open!
m_lMediaDescriptor.clear();
void LoadEnv::impl_applyPersistentWindowState(const css::uno::Reference< css::awt::XWindow >& xWindow)
{ // no window -> action not possible if (!xWindow.is()) return;
// window already visible -> do nothing! If we use a "recycle frame" for loading ... // the current position and size must be used.
css::uno::Reference< css::awt::XWindow2 > xVisibleCheck(xWindow, css::uno::UNO_QUERY); if (
(xVisibleCheck.is() ) &&
(xVisibleCheck->isVisible())
) return;
// SOLAR SAFE ->
{
SolarMutexGuard aSolarGuard1;
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow); if (!pWindow) return;
// don't overwrite this special state!
WorkWindow* pWorkWindow = static_cast<WorkWindow*>(pWindow.get()); if (pWorkWindow->IsMinimized()) return;
} // <- SOLAR SAFE
// no filter -> no module -> no persistent window state
OUString sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(
utl::MediaDescriptor::PROP_FILTERNAME,
OUString()); if (sFilter.isEmpty()) return;
try
{ // retrieve the module name from the filter configuration
css::uno::Reference< css::container::XNameAccess > xFilterCfg(
xContext->getServiceManager()->createInstanceWithContext(SERVICENAME_FILTERFACTORY, xContext),
css::uno::UNO_QUERY_THROW);
::comphelper::SequenceAsHashMap lProps (xFilterCfg->getByName(sFilter));
OUString sModule = lProps.getUnpackedValueOrDefault(FILTER_PROPNAME_ASCII_DOCUMENTSERVICE, OUString());
// get access to the configuration of this office module
css::uno::Reference< css::container::XNameAccess > xModuleCfg(officecfg::Setup::Office::Factories::get());
// read window state from the configuration // and apply it on the window. // Do nothing, if no configuration entry exists!
OUString sWindowState;
// Don't look for persistent window attributes when used through LibreOfficeKit if( !comphelper::LibreOfficeKit::isActive() )
comphelper::ConfigurationHelper::readRelativeKey(xModuleCfg, sModule, u"ooSetupFactoryWindowAttributes"_ustr) >>= sWindowState;
if (!sWindowState.isEmpty())
{ // SOLAR SAFE ->
SolarMutexGuard aSolarGuard;
// We have to retrieve the window pointer again. Because nobody can guarantee // that the XWindow was not disposed in between .-) // But if we get a valid pointer we can be sure, that it's the system window pointer // we already checked and used before. Because nobody recycle the same uno reference for // a new internal c++ implementation ... hopefully .-))
VclPtr<vcl::Window> pWindowCheck = VCLUnoHelper::GetWindow(xWindow); if (! pWindowCheck) return;
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.