/* -*- 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; usingnamespace ::com::sun::star::uno; usingnamespace ::com::sun::star::ucb; usingnamespace ::com::sun::star::frame; usingnamespace ::com::sun::star::lang; using ::com::sun::star::awt::XWindow; using ::com::sun::star::beans::PropertyValue; using ::com::sun::star::document::XViewDataSupplier; using ::com::sun::star::container::XIndexContainer;
namespace { /// Asks the user if editing a read-only document is really wanted. class SfxEditDocumentDialog : public weld::MessageDialogController
{ public:
SfxEditDocumentDialog(weld::Widget* pParent);
};
bool AskPasswordToModify_Impl( const uno::Reference< task::XInteractionHandler >& xHandler, const OUString& aPath, const std::shared_ptr<const SfxFilter>& pFilter, sal_uInt32 nPasswordHash, const uno::Sequence< beans::PropertyValue >& aInfo )
{ // TODO/LATER: In future the info should replace the direct hash completely bool bResult = ( !nPasswordHash && !aInfo.hasElements() );
SAL_WARN_IF( !(pFilter && ( pFilter->GetFilterFlags() & SfxFilterFlags::PASSWORDTOMODIFY )), "sfx.view", "PasswordToModify feature is active for a filter that does not support it!");
void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
{
SfxObjectShell* pSh = GetObjectShell(); switch ( rReq.GetSlot() )
{ case SID_EDITDOC: case SID_READONLYDOC:
{ // Due to Double occupancy in toolboxes (with or without Ctrl), // it is also possible that the slot is enabled, but Ctrl-click // despite this is not! if( !pSh || !pSh->HasName() || !(pSh->Get_Impl()->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT )) break;
if (pSh->isEditDocLocked()) break;
// Only change read-only UI and remove info bar when we succeed struct ReadOnlyUIGuard
{
SfxViewFrame* m_pFrame;
SfxObjectShell* m_pSh;
SfxMedium* m_pMed = nullptr; bool m_bSetRO;
ReadOnlyUIGuard(SfxViewFrame* pFrame, SfxObjectShell* p_Sh)
: m_pFrame(pFrame), m_pSh(p_Sh), m_bSetRO(p_Sh->IsReadOnlyUI())
{}
~ReadOnlyUIGuard() COVERITY_NOEXCEPT_FALSE
{ if (m_bSetRO != m_pSh->IsReadOnlyUI())
{
m_pSh->SetReadOnlyUI(m_bSetRO); if (!m_bSetRO)
m_pFrame->RemoveInfoBar(u"readonly"); if (m_pMed)
{ boolconst isEnableSetModified(m_pSh->IsEnableSetModified());
m_pSh->EnableSetModified(false); // tdf#116066: DoSaveCompleted should be called after SetReadOnlyUI
m_pSh->DoSaveCompleted(m_pMed);
m_pSh->Broadcast(SfxHint(SfxHintId::ModeChanged));
m_pSh->EnableSetModified(isEnableSetModified);
}
}
}
} aReadOnlyUIGuard(this, pSh);
GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet ); return;
}
StreamMode nOpenMode; bool bNeedsReload = false; bool bPasswordEntered = false; if ( !pSh->IsReadOnly() )
{ // Save and reload Readonly if( pSh->IsModified() )
{ if ( pSh->PrepareClose() )
{ // the storing could let the medium be changed
pMed = pSh->GetMedium();
bNeedsReload = true;
} else
{
rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), false ) ); return;
}
}
nOpenMode = SFX_STREAM_READONLY;
aReadOnlyUIGuard.m_bSetRO = true;
} else
{ if ( pSh->IsReadOnlyMedium()
&& ( pSh->GetModifyPasswordHash() || pSh->GetModifyPasswordInfo().hasElements() )
&& !pSh->IsModifyPasswordEntered() )
{ const OUString aDocumentName = INetURLObject( pMed->GetOrigURL() ).GetMainURL( INetURLObject::DecodeMechanism::WithCharset ); if( !AskPasswordToModify_Impl( pMed->GetInteractionHandler(), aDocumentName, pMed->GetFilter(), pSh->GetModifyPasswordHash(), pSh->GetModifyPasswordInfo() ) )
{ // this is a read-only document, if it has "Password to modify" // the user should enter password before he can edit the document
rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), false ) ); return;
}
// if only the view was in the readonly mode then there is no need to do the reload if ( !pSh->IsReadOnlyMedium() )
{ // SetReadOnlyUI causes recomputation of window title, using // open mode among other things, so call SetOpenMode before // SetReadOnlyUI:
pMed->SetOpenMode( nOpenMode ); return;
}
}
if ( rReq.IsAPI() )
{ // Control through API if r/w or r/o const SfxBoolItem* pEditItem = rReq.GetArg<SfxBoolItem>(SID_EDITDOC); if ( pEditItem )
nOpenMode = pEditItem->GetValue() ? SFX_STREAM_READWRITE : SFX_STREAM_READONLY;
}
// -> tdf#82744 // the logic below is following: // if the document seems not to need to be reloaded // and the physical name is different to the logical one, // then on file system it can be checked that the copy is still newer than the original and no document reload is required. // Did some semplification to enhance readability of the 'if' expression // // when the 'http/https' protocol is active, the bool bPhysObjIsYounger relies upon the getlastmodified Property of a WebDAV resource. // Said property should be implemented, but sometimes it's not. // implemented. On this case the reload activated here will not work properly. // TODO: change the check age method for WebDAV to etag (entity-tag) property value, need some rethinking, since the // etag tells that the cache representation (e.g. in LO) is different from the one on the server, // but tells nothing about the age // Details at this link: http://tools.ietf.org/html/rfc4918#section-15, section 15.7 bool bIsWebDAV = aMedObj.isAnyKnownWebDAVScheme();
// tdf#118938 Reload the document when the user enters the editing password, // even if the physical name isn't different to the logical name. if ( ( !bNeedsReload && ( ( aMedObj.GetProtocol() == INetProtocol::File &&
( aMedObj.getFSysPath( FSysStyle::Detect ) != aPhysObj.getFSysPath( FSysStyle::Detect )
|| bPasswordEntered ) &&
!physObjIsOlder(aMedObj, aPhysObj))
|| (bIsWebDAV && !physObjIsOlder(aMedObj, aPhysObj))
|| ( pMed->IsRemote() && !bIsWebDAV ) ) )
|| pVersionItem ) // <- tdf#82744
{ bool bOK = false; bool bRetryIgnoringLock = false; bool bOpenTemplate = false;
std::optional<bool> aOrigROVal; if (!pVersionItem)
{ auto pRO = pMed->GetItemSet().GetItem<SfxBoolItem>(SID_DOC_READONLY, false); if (pRO)
aOrigROVal = pRO->GetValue();
} do {
LockFileEntry aLockData; if ( !pVersionItem )
{ if (bRetryIgnoringLock)
pMed->ResetError();
bool bHasStorage = pMed->HasStorage_Impl(); // switching edit mode could be possible without reload if ( bHasStorage && pMed->GetStorage() == pSh->GetStorage() )
{ // TODO/LATER: faster creation of copy if ( !pSh->ConnectTmpStorage_Impl( pMed->GetStorage(), pMed ) ) return;
}
pMed->CloseAndRelease();
pMed->SetOpenMode( nOpenMode ); // We need to clear the SID_DOC_READONLY item from the set, to allow // MediaDescriptor::impl_openStreamWithURL (called indirectly by // SfxMedium::CompleteReOpen) to properly fill input stream of the // descriptor, even when the file can't be open in read-write mode. // Only then can following call to SfxMedium::LockOrigFileOnDemand // return proper information about who has locked the file, to show // in the SfxQueryOpenAsTemplate box below; otherwise it exits right // after call to SfxMedium::GetMedium_Impl. This mimics what happens // when the file is opened initially, when filter detection code also // calls MediaDescriptor::impl_openStreamWithURL without the item set.
pMed->GetItemSet().ClearItem(SID_DOC_READONLY);
pMed->CompleteReOpen();
pMed->GetItemSet().Put(
SfxBoolItem(SID_DOC_READONLY, !(nOpenMode & StreamMode::WRITE))); if ( nOpenMode & StreamMode::WRITE )
{ auto eResult = pMed->LockOrigFileOnDemand( true, true, bRetryIgnoringLock, &aLockData);
bRetryIgnoringLock
= eResult == SfxMedium::LockFileResult::FailedLockFile;
}
// LockOrigFileOnDemand might set the readonly flag itself, it should be set back
pMed->GetItemSet().Put( SfxBoolItem( SID_DOC_READONLY, !( nOpenMode & StreamMode::WRITE ) ) );
if ( !pMed->GetErrorCode() )
bOK = true;
}
if( !bOK )
{ if (nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI())
{ // css::sdbcx::User offering to open it as a template
SfxQueryOpenAsTemplate aBox(GetWindow().GetFrameWeld(),
bRetryIgnoringLock, aLockData);
short nUserAnswer = aBox.run();
bOpenTemplate = RET_YES == nUserAnswer; // Always reset this here to avoid infinite loop
bRetryIgnoringLock = RET_IGNORE == nUserAnswer; if (RET_CANCEL == nUserAnswer)
pMed->AddToCheckEditableWorkerList();
} else
bRetryIgnoringLock = false;
}
} while ( !bOK && bRetryIgnoringLock );
case SID_RELOAD:
{ // Due to Double occupancy in toolboxes (with or without Ctrl), // it is also possible that the slot is enabled, but Ctrl-click // despite this is not! if ( !pSh || !pSh->CanReload_Impl() ) break;
SfxApplication* pApp = SfxGetpApp(); const SfxBoolItem* pForceReloadItem = rReq.GetArg<SfxBoolItem>(SID_FORCERELOAD); if( pForceReloadItem && !pForceReloadItem->GetValue() &&
!pSh->GetMedium()->IsExpired() ) return; if( m_pImpl->bReloading || pSh->IsInModalMode() ) return;
// AutoLoad is prohibited if possible const SfxBoolItem* pAutoLoadItem = rReq.GetArg<SfxBoolItem>(SID_AUTOLOAD); if ( pAutoLoadItem && pAutoLoadItem->GetValue() &&
GetFrame().IsAutoLoadLocked_Impl() ) return;
SfxObjectShellLock xOldObj( pSh );
m_pImpl->bReloading = true; const SfxStringItem* pURLItem = rReq.GetArg<SfxStringItem>(SID_FILE_NAME); // Open as editable? bool bForEdit = !pSh->IsReadOnly();
// If possible ask the User bool bDo = GetViewShell()->PrepareClose(); const SfxBoolItem* pSilentItem = rReq.GetArg<SfxBoolItem>(SID_SILENT); if (getenv("SAL_NO_QUERYSAVE"))
bDo = true; elseif (bDo && GetFrame().DocIsModified_Impl() && !rReq.IsAPI()
&& (!pSilentItem || !pSilentItem->GetValue()))
{
std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
GetWindow().GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo,
SfxResId(STR_QUERY_LASTVERSION)));
bDo = RET_YES == xBox->run();
}
// Empty existing SfxMDIFrames for this Document // in native format or R/O, open it now for editing?
SfxObjectShellLock xNewObj;
// collect the views of the document // TODO: when UNO ViewFactories are available for SFX-based documents, the below code should // be UNOized, too typedef ::std::pair< Reference< XFrame >, SfxInterfaceId > ViewDescriptor;
::std::vector< ViewDescriptor > aViewFrames;
SfxViewFrame *pView = GetFirst( xOldObj ); while ( pView )
{
Reference< XFrame > xFrame( pView->GetFrame().GetFrameInterface() );
SAL_WARN_IF( !xFrame.is(), "sfx.view", "SfxViewFrame::ExecReload_Impl: no XFrame?!");
aViewFrames.emplace_back( xFrame, pView->GetCurViewId() );
// let the current security settings be checked again
pNewSet->Put( SfxUInt16Item( SID_MACROEXECMODE, document::MacroExecMode::USE_CONFIG ) );
if ( pSh->IsOriginallyReadOnlyMedium()
|| pSh->IsOriginallyLoadedReadOnlyMedium() ) // edit mode is switched or reload of readonly document
pNewSet->Put( SfxBoolItem( SID_DOC_READONLY, true ) ); else // Reload of file opened for writing
pNewSet->ClearItem( SID_DOC_READONLY );
}
// If a salvaged file is present, do not enclose the OrigURL // again, since the Template is invalid after reload. const SfxStringItem* pSalvageItem = SfxItemSet::GetItem<SfxStringItem>(&*pNewSet, SID_DOC_SALVAGE, false); if( pSalvageItem )
{
pNewSet->ClearItem( SID_DOC_SALVAGE );
}
#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT // TODO/LATER: Temporary solution, the SfxMedium must know the original URL as aLogicName // SfxMedium::Transfer_Impl() will be forbidden then. if ( xOldObj->IsDocShared() )
pNewSet->Put( SfxStringItem( SID_FILE_NAME, xOldObj->GetSharedFileURL() ) ); #endif if ( pURLItem )
pNewSet->Put( SfxStringItem( SID_REFERER, pMedium->GetName() ) ); else
pNewSet->Put( SfxStringItem( SID_REFERER, OUString() ) );
if (!pInteractionItem)
{
Reference < task::XInteractionHandler2 > xHdl = task::InteractionHandler::createWithParent( ::comphelper::getProcessComponentContext(), nullptr ); if (xHdl.is())
pNewSet->Put( SfxUnoAnyItem(SID_INTERACTIONHANDLER,css::uno::Any(xHdl)) );
}
if (!pMacroExecItem)
pNewSet->Put( SfxUInt16Item(SID_MACROEXECMODE,css::document::MacroExecMode::USE_CONFIG) ); if (!pDocTemplateItem)
pNewSet->Put( SfxUInt16Item(SID_UPDATEDOCMODE,css::document::UpdateDocMode::ACCORDING_TO_CONFIG) );
xOldObj->SetModified( false ); // Do not cache the old Document! Is invalid when loading // another document.
#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT if ( xNewObj->IsDocShared() )
{ // the file is shared but the closing can change the sharing control file
xOldObj->DoNotCleanShareControlFile();
} #endif // the Reload and Silent items were only temporary, remove them
xNewObj->GetMedium()->GetItemSet().ClearItem( SID_RELOAD );
xNewObj->GetMedium()->GetItemSet().ClearItem( SID_SILENT );
TransformItems( SID_OPENDOC, xNewObj->GetMedium()->GetItemSet(), aLoadArgs );
try
{ for (autoconst& viewFrame : aViewFrames)
{
LoadViewIntoFrame_Impl( *xNewObj, viewFrame.first, aLoadArgs, viewFrame.second, false);
}
aViewFrames.clear();
} catch( const Exception& )
{ // close the remaining frames // Don't catch exceptions herein, if this fails, then we're left in an indetermined state, and // crashing is better than trying to proceed for (autoconst& viewFrame : aViewFrames)
{
Reference< util::XCloseable > xClose( viewFrame.first, UNO_QUERY_THROW );
xClose->close( true );
}
aViewFrames.clear();
}
// tdf#126006 Calc needs to reload the notebookbar after closing the document if (!sReloadNotebookBar.isEmpty())
sfx2::SfxNotebookBar::ReloadNotebookBar(sReloadNotebookBar);
}
// Record as done
rReq.Done( true );
rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), true)); return;
} else
{ // Record as not done
rReq.Done();
rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), false));
m_pImpl->bReloading = false; return;
}
}
}
}
void SfxViewFrame::StateReload_Impl( SfxItemSet& rSet )
{
SfxObjectShell* pSh = GetObjectShell(); if ( !pSh )
{ // I'm just on reload and am yielding myself ... return;
}
case SID_RELOAD:
{ if ( !pSh->CanReload_Impl() || pSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
rSet.DisableItem(nWhich); else
{ // If any ChildFrame is reloadable, the slot is enabled, // so you can perform CTRL-Reload
rSet.Put( SfxBoolItem( nWhich, false));
}
break;
}
}
}
}
void SfxViewFrame::ExecHistory_Impl( SfxRequest &rReq )
{ // Is there an Undo-Manager on the top Shell?
SfxShell *pSh = GetDispatcher()->GetShell(0); if (!pSh) return;
SfxUndoManager* pShUndoMgr = pSh->GetUndoManager(); bool bOK = false; if ( pShUndoMgr )
{ switch ( rReq.GetSlot() )
{ case SID_CLEARHISTORY:
pShUndoMgr->Clear();
bOK = true; break;
case SID_UNDO:
pShUndoMgr->Undo();
GetBindings().InvalidateAll(false);
bOK = true; break;
case SID_REDO:
pShUndoMgr->Redo();
GetBindings().InvalidateAll(false);
bOK = true; break;
case SID_REPEAT: if ( pSh->GetRepeatTarget() )
pShUndoMgr->Repeat( *pSh->GetRepeatTarget() );
bOK = true; break;
}
} elseif ( GetViewShell() )
{ // The SW has its own undo in the View const SfxPoolItemHolder& rResult(GetViewShell()->ExecuteSlot(rReq)); if (rResult)
bOK = static_cast<const SfxBoolItem*>(rResult.getItem())->GetValue();
}
rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bOK ) );
rReq.Done();
}
void SfxViewFrame::StateHistory_Impl( SfxItemSet &rSet )
{ // Search for Undo-Manager
SfxShell *pSh = GetDispatcher()->GetShell(0); if ( !pSh ) // I'm just on reload and am yielding myself ... return;
SfxUndoManager *pShUndoMgr = pSh->GetUndoManager(); if ( !pShUndoMgr )
{ // The SW has its own undo in the View
SfxWhichIter aIter( rSet );
SfxViewShell *pViewSh = GetViewShell(); if( !pViewSh ) return; for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() )
pViewSh->GetSlotState( nSID, nullptr, &rSet ); return;
}
void SfxViewFrame::PopShellAndSubShells_Impl( SfxViewShell& i_rViewShell )
{
i_rViewShell.PopSubShells_Impl();
sal_uInt16 nLevel = m_pDispatcher->GetShellLevel( i_rViewShell ); if ( nLevel != USHRT_MAX )
{ if ( nLevel )
{ // more sub shells on the stack, which were not affected by PopSubShells_Impl if (SfxShell *pSubShell = m_pDispatcher->GetShell( nLevel-1 ))
m_pDispatcher->Pop( *pSubShell, SfxDispatcherPopFlags::POP_UNTIL | SfxDispatcherPopFlags::POP_DELETE );
}
m_pDispatcher->Pop( i_rViewShell );
m_pDispatcher->Flush();
}
}
/* [Description]
This method empties the SfxViewFrame, i.e. takes the <SfxObjectShell> from the dispatcher and ends its <SfxListener> Relationship to this SfxObjectShell (by which they may even destroy themselves).
Thus, by invoking ReleaseObjectShell() and SetObjectShell() the SfxObjectShell can be replaced.
Between ReleaseObjectShell() and SetObjectShell() the control cannot be handed over to the system.
[Cross-reference]
<SfxViewFrame::SetObjectShell(SfxObjectShell&)>
*/ void SfxViewFrame::ReleaseObjectShell_Impl()
{
DBG_ASSERT( m_xObjSh.is(), "no SfxObjectShell to release!" );
GetFrame().ReleasingComponent_Impl(); if ( GetWindow().HasChildPathFocus( true ) )
{
GetWindow().GrabFocus();
}
DBG_ASSERT( GetFrame().IsClosing_Impl() || !GetFrame().GetFrameInterface().is(), "ViewFrame closed too early!" );
// If no saving have been made up until now, then embedded Objects should // not be saved automatically anymore. if ( GetViewShell() )
GetViewShell()->DisconnectAllClients();
Broadcast( SfxHint( SfxHintId::Dying ) );
if (SfxViewFrame::Current() == this)
SfxViewFrame::SetViewFrame( nullptr );
// Since the Dispatcher is emptied, it can not be used in any reasonable // manner, thus it is better to let the dispatcher be.
GetDispatcher()->Lock(true); deletethis;
}
auto pInfoBar = AppendInfoBar(u"readonly"_ustr, u""_ustr,
SfxResId(bSignPDF ? STR_READONLY_PDF : STR_READONLY_DOCUMENT),
InfobarType::INFO); if (!pInfoBar) return;
if (bSignPDF)
{ // SID_SIGNPDF opened a read-write PDF // read-only for signing purposes.
weld::Button& rSignButton = pInfoBar->addButton(); if (bSignWithCert)
{
rSignButton.set_label(SfxResId(STR_READONLY_FINISH_SIGN));
} else
{
rSignButton.set_label(SfxResId(STR_READONLY_SIGN));
}
void SfxViewFrame::HandleSecurityInfobar(const OUString& sSecondaryMessage)
{ if (!HasInfoBarWithID(u"securitywarn"))
{ // new info bar if (!sSecondaryMessage.isEmpty())
{ auto pInfoBar = AppendInfoBar(u"securitywarn"_ustr, SfxResId(STR_HIDDENINFO_CONTAINS).replaceAll("\n\n", " "),
sSecondaryMessage, InfobarType::WARNING); if (!pInfoBar) return;
auto aResId = STR_CONTAINS_MACROS; if (SvtSecurityOptions::IsMacroDisabled())
aResId = STR_MACROS_DISABLED; elseif (pObjImpl->aMacroMode.hasUnsignedContentError())
aResId = STR_MACROS_DISABLED_CONTENT_UNSIGNED; elseif(pObjImpl->aMacroMode.hasInvalidSignaturesError())
aResId = STR_MACROS_DISABLED_SIGNATURE_INVALID; // The idea here is to always present an infobar is there was some // macro/script related potential hazard disabled in the source document auto pInfoBar = AppendInfoBar(u"macro"_ustr, SfxResId(STR_MACROS_DISABLED_TITLE),
SfxResId(aResId), InfobarType::WARNING); if (!pInfoBar) return;
// Then show buttons to help navigate to whatever that hazard is. Whether // that is included macros, so the user could delete them. Or events bound // to scripts which could be cleared. But there are likely other cases not // captured here, which could be added, various blocked features where its // likely still worth displaying the infobar that they have been disabled, // even if we don't currently provide a way to indicate what exactly those // are and how to remove them.
// No access to macro dialog when macros are disabled globally, so return // early without adding buttons to help explore what the macros/script/events // might be. if (SvtSecurityOptions::IsMacroDisabled()) return;
// what's the difference between pObjImpl->documentStorageHasMacros() and pObjImpl->aMacroMode.hasMacroLibrary() ? bool bHasDocumentMacros = pObjImpl->aMacroMode.hasMacroLibrary();
bool SfxApplication::IsHeadlessOrUITest()
{ if (Application::IsHeadlessModeEnabled()) returntrue;
bool bRet = o3tl::IsRunningUITest(); //uitest.uicheck fails when the dialog is open for (sal_uInt16 i = 0, nCount = Application::GetCommandLineParamCount(); i < nCount; ++i)
{ if (Application::GetCommandLineParam(i) == "--nologo")
{
bRet = true; break;
}
} return bRet;
}
bool SfxApplication::IsTipOfTheDayDue()
{ constbool bShowTipOfTheDay = officecfg::Office::Common::Misc::ShowTipOfTheDay::get(); if (!bShowTipOfTheDay) returnfalse;
// show tip-of-the-day dialog ? const sal_Int32 nLastTipOfTheDay = officecfg::Office::Common::Misc::LastTipOfTheDayShown::get(); const sal_Int32 nDay = std::chrono::duration_cast<std::chrono::hours>(t0).count()/24; // days since 1970-01-01 return nDay - nLastTipOfTheDay > 0; //only once per day
}
// we know only SfxEventHint or simple SfxHint if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
{ // When the Document is loaded asynchronously, was the Dispatcher // set as ReadOnly, to what must be returned when the document itself // is not read only, and the loading is finished. switch (static_cast<const SfxEventHint&>(rHint).GetEventId())
{ case SfxEventHintId::ModifyChanged:
{
SfxBindings& rBind = GetBindings();
rBind.Invalidate( SID_DOC_MODIFIED );
rBind.Invalidate( SID_RELOAD );
rBind.Invalidate( SID_EDITDOC ); break;
}
case SfxEventHintId::OpenDoc: case SfxEventHintId::CreateDoc:
{ if ( !m_xObjSh.is() ) break;
if (vcl::CommandInfoProvider::GetModuleIdentifier(GetFrame().GetFrameInterface()) == "com.sun.star.text.TextDocument")
sfx2::SfxNotebookBar::ReloadNotebookBar(u"modules/swriter/ui/");
if (SfxClassificationHelper::IsClassified(m_xObjSh->getDocProperties()))
{ // Document has BAILS properties, display an infobar accordingly.
SfxClassificationHelper aHelper(m_xObjSh->getDocProperties());
aHelper.UpdateInfobar(*this);
}
// don't show Track Changes infobar, if Track Changes toolbar is visible if (aInfobarData.msId == "hiddentrackchanges")
{ if (auto xLayoutManager = getLayoutManager(GetFrame()))
{
--> --------------------
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.