summaryrefslogtreecommitdiff
path: root/framework/source/services/autorecovery.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'framework/source/services/autorecovery.cxx')
-rw-r--r--framework/source/services/autorecovery.cxx416
1 files changed, 284 insertions, 132 deletions
diff --git a/framework/source/services/autorecovery.cxx b/framework/source/services/autorecovery.cxx
index 9f514ae833..41dbe9b603 100644
--- a/framework/source/services/autorecovery.cxx
+++ b/framework/source/services/autorecovery.cxx
@@ -28,10 +28,10 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_framework.hxx"
#include "services/autorecovery.hxx"
+#include <loadenv/loadenv.hxx>
//_______________________________________________
// own includes
-#include <loadenv/loaddispatchlistener.hxx>
#include <loadenv/targethelper.hxx>
#include <pattern/frame.hxx>
#include <threadhelp/readguard.hxx>
@@ -47,6 +47,8 @@
// interface includes
#include <com/sun/star/ucb/NameClash.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/frame/XLoadable.hpp>
+#include <com/sun/star/frame/XModel2.hpp>
#include <com/sun/star/frame/XModuleManager.hpp>
#include <com/sun/star/frame/XTitle.hpp>
#include <com/sun/star/frame/XFrame.hpp>
@@ -67,6 +69,7 @@
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/container/XContainerQuery.hpp>
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentRecovery.hpp>
#include <com/sun/star/util/XCloseable.hpp>
#include <com/sun/star/awt/XWindow2.hpp>
#include <com/sun/star/task/XStatusIndicatorFactory.hpp>
@@ -75,10 +78,12 @@
// other includes
#include <comphelper/configurationhelper.hxx>
#include <comphelper/mediadescriptor.hxx>
+#include <comphelper/namedvaluecollection.hxx>
#include <vcl/svapp.hxx>
#include <unotools/pathoptions.hxx>
#include <tools/link.hxx>
#include <tools/string.hxx>
+#include <tools/diagnose_ex.h>
#include <unotools/tempfile.hxx>
#include <ucbhelper/content.hxx>
@@ -88,6 +93,7 @@
#include <unotools/bootstrap.hxx>
#include <unotools/configmgr.hxx>
#include <svl/documentlockfile.hxx>
+#include <cppuhelper/exc_hlp.hxx>
#include <tools/urlobj.hxx>
@@ -98,6 +104,23 @@
namespace css = ::com::sun::star;
#endif
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::uno::UNO_SET_THROW;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::container::XEnumeration;
+using ::com::sun::star::document::XDocumentRecovery;
+using ::com::sun::star::frame::XModel2;
+using ::com::sun::star::frame::XModel;
+using ::com::sun::star::frame::XFrame;
+using ::com::sun::star::frame::XController2;
+using ::com::sun::star::frame::XLoadable;
+using ::com::sun::star::frame::XStorable;
+using ::com::sun::star::lang::XComponent;
+
namespace fpf = ::framework::pattern::frame;
namespace framework
@@ -131,6 +154,7 @@ static const ::rtl::OUString CFG_ENTRY_PROP_DOCUMENTSTATE = ::rtl::OUString:
static const ::rtl::OUString CFG_ENTRY_PROP_FILTER = ::rtl::OUString::createFromAscii("Filter" );
static const ::rtl::OUString CFG_ENTRY_PROP_TITLE = ::rtl::OUString::createFromAscii("Title" );
static const ::rtl::OUString CFG_ENTRY_PROP_ID = ::rtl::OUString::createFromAscii("ID" );
+static const ::rtl::OUString CFG_ENTRY_PROP_VIEWNAMES = ::rtl::OUString::createFromAscii("ViewNames" );
static const ::rtl::OUString FILTER_PROP_TYPE = ::rtl::OUString::createFromAscii("Type" );
static const ::rtl::OUString FILTER_PROP_NAME = ::rtl::OUString::createFromAscii("Name" );
@@ -140,6 +164,7 @@ static const ::rtl::OUString DOCINFO_PROP_TEMPLATE = ::rtl::OUString::
// setup.xcu
static const ::rtl::OUString CFG_ENTRY_PROP_EMPTYDOCUMENTURL = ::rtl::OUString::createFromAscii("ooSetupFactoryEmptyDocumentURL");
static const ::rtl::OUString CFG_ENTRY_PROP_DEFAULTFILTER = ::rtl::OUString::createFromAscii("ooSetupFactoryDefaultFilter" );
+static const ::rtl::OUString CFG_ENTRY_PROP_FACTORYSERVICE = ::rtl::OUString::createFromAscii("ooSetupFactoryDocumentService" );
static const ::rtl::OUString EVENT_ON_NEW = ::rtl::OUString::createFromAscii("OnNew" );
static const ::rtl::OUString EVENT_ON_LOAD = ::rtl::OUString::createFromAscii("OnLoad" );
@@ -619,7 +644,7 @@ void SAL_CALL AutoRecovery::dispatch(const css::util::URL&
// dont enable AutoSave hardly !
// reload configuration to know the current state.
implts_readAutoSaveConfig();
- implts_actualizeTimer();
+ implts_updateTimer();
// can it happen that might be the listener was stopped ? .-)
// make sure it runs always ... even if AutoSave itself was disabled temporarly.
implts_startListening();
@@ -775,7 +800,7 @@ void AutoRecovery::implts_dispatch(const DispatchParams& aParams)
// <- SAFE ----------------------------------
// depends on bAllowAutoSaveReactivation implicitly by looking on m_eJob=E_AUTO_SAVE! see before ...
- implts_actualizeTimer();
+ implts_updateTimer();
if (bAllowAutoSaveReactivation)
implts_startListening();
@@ -791,7 +816,7 @@ void SAL_CALL AutoRecovery::addStatusListener(const css::uno::Reference< css::fr
// container is threadsafe by using a shared mutex!
m_lListener.addInterface(aURL.Complete, xListener);
- // REINTRANT !? -> --------------------------------
+ // REENTRANT !? -> --------------------------------
CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
// THREAD SAFE -> ----------------------------------
@@ -845,7 +870,7 @@ void SAL_CALL AutoRecovery::notifyEvent(const css::document::EventObject& aEvent
else
if (aEvent.EventName.equals(EVENT_ON_MODIFYCHANGED))
{
- implts_actualizeModifiedState(xDocument);
+ implts_updateModifiedState(xDocument);
}
/* at least one document starts saving process =>
Our application code isnt ready for multiple save requests
@@ -954,7 +979,7 @@ void SAL_CALL AutoRecovery::changesOccurred(const css::util::ChangesEvent& aEven
// Note: This call stops the timer and starts it again.
// But it checks the different timer states internaly and
// may be supress the restart!
- implts_actualizeTimer();
+ implts_updateTimer();
}
//-----------------------------------------------
@@ -1096,7 +1121,7 @@ void AutoRecovery::implts_readConfig()
css::uno::Reference< css::container::XHierarchicalNameAccess > xCommonRegistry(implts_openConfig(), css::uno::UNO_QUERY);
- // REINTRANT -> --------------------------------
+ // REENTRANT -> --------------------------------
CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_ADD_REMOVE);
// THREADSAFE -> -------------------------------
@@ -1108,7 +1133,7 @@ void AutoRecovery::implts_readConfig()
// <- THREADSAFE -------------------------------
aCacheLock.unlock();
- // <- REINTRANT --------------------------------
+ // <- REENTRANT --------------------------------
css::uno::Any aValue;
@@ -1123,7 +1148,7 @@ void AutoRecovery::implts_readConfig()
sal_Int32 c = lItems.getLength();
sal_Int32 i = 0;
- // REINTRANT -> --------------------------
+ // REENTRANT -> --------------------------
aCacheLock.lock(LOCK_FOR_CACHE_ADD_REMOVE);
for (i=0; i<c; ++i)
@@ -1143,7 +1168,8 @@ void AutoRecovery::implts_readConfig()
xItem->getPropertyValue(CFG_ENTRY_PROP_DOCUMENTSTATE) >>= aInfo.DocumentState;
xItem->getPropertyValue(CFG_ENTRY_PROP_MODULE ) >>= aInfo.AppModule ;
xItem->getPropertyValue(CFG_ENTRY_PROP_TITLE ) >>= aInfo.Title ;
- implts_specifyAppModuleAndFactoryURL(aInfo);
+ xItem->getPropertyValue(CFG_ENTRY_PROP_VIEWNAMES ) >>= aInfo.ViewNames ;
+ implts_specifyAppModuleAndFactory(aInfo);
implts_specifyDefaultFilterAndExtension(aInfo);
if (pItems[i].indexOf(RECOVERY_ITEM_BASE_IDENTIFIER)==0)
@@ -1173,10 +1199,10 @@ void AutoRecovery::implts_readConfig()
}
aCacheLock.unlock();
- // <- REINTRANT --------------------------
+ // <- REENTRANT --------------------------
}
- implts_actualizeTimer();
+ implts_updateTimer();
}
//-----------------------------------------------
@@ -1241,17 +1267,12 @@ void AutoRecovery::implts_specifyDefaultFilterAndExtension(AutoRecovery::TDocume
}
//-----------------------------------------------
-void AutoRecovery::implts_specifyAppModuleAndFactoryURL(AutoRecovery::TDocumentInfo& rInfo)
+void AutoRecovery::implts_specifyAppModuleAndFactory(AutoRecovery::TDocumentInfo& rInfo)
{
- if (
- (!rInfo.AppModule.getLength()) &&
- (!rInfo.Document.is() )
- )
- {
- throw css::uno::RuntimeException(
- ::rtl::OUString::createFromAscii("Cant find out the application module nor its factory URL, if no application module (or a suitable) document is known!"),
- static_cast< css::frame::XDispatch* >(this));
- }
+ ENSURE_OR_THROW2(
+ rInfo.AppModule.getLength() || rInfo.Document.is(),
+ "Cant find out the application module nor its factory URL, if no application module (or a suitable) document is known!",
+ *this );
// SAFE -> ----------------------------------
ReadGuard aReadLock(m_aLock);
@@ -1267,6 +1288,65 @@ void AutoRecovery::implts_specifyAppModuleAndFactoryURL(AutoRecovery::TDocumentI
::comphelper::SequenceAsHashMap lModuleDescription(xModuleConfig->getByName(rInfo.AppModule));
lModuleDescription[CFG_ENTRY_PROP_EMPTYDOCUMENTURL] >>= rInfo.FactoryURL;
+ lModuleDescription[CFG_ENTRY_PROP_FACTORYSERVICE] >>= rInfo.FactoryService;
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_collectActiveViewNames( AutoRecovery::TDocumentInfo& i_rInfo )
+{
+ ENSURE_OR_THROW2( i_rInfo.Document.is(), "need at document, at the very least", *this );
+
+ i_rInfo.ViewNames.realloc(0);
+
+ // obtain list of controllers of this document
+ ::std::vector< ::rtl::OUString > aViewNames;
+ const Reference< XModel2 > xModel( i_rInfo.Document, UNO_QUERY );
+ if ( xModel.is() )
+ {
+ const Reference< XEnumeration > xEnumControllers( xModel->getControllers() );
+ while ( xEnumControllers->hasMoreElements() )
+ {
+ const Reference< XController2 > xController( xEnumControllers->nextElement(), UNO_QUERY );
+ ::rtl::OUString sViewName;
+ if ( xController.is() )
+ sViewName = xController->getViewControllerName();
+ OSL_ENSURE( sViewName.getLength(), "AutoRecovery::implts_collectActiveViewNames: (no XController2 ->) no view name -> no recovery of this view!" );
+
+ if ( sViewName.getLength() )
+ aViewNames.push_back( sViewName );
+ }
+ }
+ else
+ {
+ const Reference< XController2 > xController( xModel->getCurrentController(), UNO_QUERY );
+ ::rtl::OUString sViewName;
+ if ( xController.is() )
+ sViewName = xController->getViewControllerName();
+ OSL_ENSURE( sViewName.getLength(), "AutoRecovery::implts_collectActiveViewNames: (no XController2 ->) no view name -> no recovery of this view!" );
+
+ if ( sViewName.getLength() )
+ aViewNames.push_back( sViewName );
+ }
+
+ i_rInfo.ViewNames.realloc( aViewNames.size() );
+ ::std::copy( aViewNames.begin(), aViewNames.end(), i_rInfo.ViewNames.getArray() );
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_persistAllActiveViewNames()
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ // This list will be filled with every document
+ AutoRecovery::TDocumentList::iterator pIt;
+ for ( pIt = m_lDocCache.begin();
+ pIt != m_lDocCache.end() ;
+ ++pIt )
+ {
+ implts_collectActiveViewNames( *pIt );
+ implts_flushConfigItem( *pIt );
+ }
}
//-----------------------------------------------
@@ -1319,6 +1399,7 @@ void AutoRecovery::implts_flushConfigItem(const AutoRecovery::TDocumentInfo& rIn
xSet->setPropertyValue(CFG_ENTRY_PROP_DOCUMENTSTATE, css::uno::makeAny(rInfo.DocumentState));
xSet->setPropertyValue(CFG_ENTRY_PROP_MODULE , css::uno::makeAny(rInfo.AppModule ));
xSet->setPropertyValue(CFG_ENTRY_PROP_TITLE , css::uno::makeAny(rInfo.Title ));
+ xSet->setPropertyValue(CFG_ENTRY_PROP_VIEWNAMES , css::uno::makeAny(rInfo.ViewNames ));
if (bNew)
xModify->insertByName(sID, css::uno::makeAny(xSet));
@@ -1478,7 +1559,7 @@ void AutoRecovery::implts_stopModifyListeningOnDoc(AutoRecovery::TDocumentInfo&
}
//-----------------------------------------------
-void AutoRecovery::implts_actualizeTimer()
+void AutoRecovery::implts_updateTimer()
{
implts_stopTimer();
@@ -1569,7 +1650,7 @@ IMPL_LINK(AutoRecovery, implts_timerExpired, void*, EMPTYARG)
m_eTimerType = AutoRecovery::E_POLL_TILL_AUTOSAVE_IS_ALLOWED;
aWriteLock.unlock();
// <- SAFE ------------------------------
- implts_actualizeTimer();
+ implts_updateTimer();
return 0;
}
@@ -1584,7 +1665,7 @@ IMPL_LINK(AutoRecovery, implts_timerExpired, void*, EMPTYARG)
sal_Bool bUserIdle = (Application::GetLastInputInterval()>MIN_TIME_FOR_USER_IDLE);
if (!bUserIdle)
{
- implts_actualizeTimer();
+ implts_updateTimer();
return 0;
}
}
@@ -1625,7 +1706,7 @@ IMPL_LINK(AutoRecovery, implts_timerExpired, void*, EMPTYARG)
aWriteLock.unlock();
// <- SAFE ----------------------------------
- implts_actualizeTimer();
+ implts_updateTimer();
}
catch(const css::uno::Exception&)
{
@@ -1662,7 +1743,7 @@ void AutoRecovery::implts_registerDocument(const css::uno::Reference< css::frame
// notification for already existing document !
// Can happen if events came in asynchronous on recovery time.
// Then our cache was filled from the configuration ... but now we get some
- // asynchronous events from the global event broadcaster. We must be shure that
+ // asynchronous events from the global event broadcaster. We must be sure that
// we dont add the same document more then once.
AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument);
if (pIt != m_lDocCache.end())
@@ -1670,7 +1751,7 @@ void AutoRecovery::implts_registerDocument(const css::uno::Reference< css::frame
// Normaly nothing must be done for this "late" notification.
// But may be the modified state was changed inbetween.
// Check it ...
- implts_actualizeModifiedState(xDocument);
+ implts_updateModifiedState(xDocument);
return;
}
@@ -1695,6 +1776,11 @@ void AutoRecovery::implts_registerDocument(const css::uno::Reference< css::frame
if (!xDesktop.is())
return;
+ // if the document doesn't support the XDocumentRecovery interface, we're not interested in it.
+ Reference< XDocumentRecovery > xDocRecovery( xDocument, UNO_QUERY );
+ if ( !xDocRecovery.is() )
+ return;
+
// get all needed informations of this document
// We need it to update our cache or to locate already existing elements there!
AutoRecovery::TDocumentInfo aNew;
@@ -1714,7 +1800,7 @@ void AutoRecovery::implts_registerDocument(const css::uno::Reference< css::frame
// <- SAFE ----------------------------------
// classify the used application module, which is used by this document.
- implts_specifyAppModuleAndFactoryURL(aNew);
+ implts_specifyAppModuleAndFactory(aNew);
// Hack! Check for "illegal office documents" ... as e.g. the Basic IDE
// Its not realy a full featured office document. It doesnt provide an URL, any filter, a factory URL etcpp.
@@ -1723,7 +1809,12 @@ void AutoRecovery::implts_registerDocument(const css::uno::Reference< css::frame
(!aNew.OrgURL.getLength() ) &&
(!aNew.FactoryURL.getLength())
)
- return;
+ {
+ OSL_ENSURE( false, "AutoRecovery::implts_registerDocument: this should not happen anymore!" );
+ // nowadays, the Basic IDE should already die on the "supports XDocumentRecovery" check. And no other known
+ // document type fits in here ...
+ return;
+ }
// By the way - get some information about the default format for saving!
// and save an information about the real used filter by this document.
@@ -1744,7 +1835,6 @@ void AutoRecovery::implts_registerDocument(const css::uno::Reference< css::frame
if (xModifyCheck->isModified())
{
aNew.DocumentState |= AutoRecovery::E_MODIFIED;
- aNew.DocumentState |= AutoRecovery::E_MODIFIED_SINCE_LAST_AUTOSAVE;
}
aCacheLock.lock(LOCK_FOR_CACHE_ADD_REMOVE);
@@ -1752,7 +1842,7 @@ void AutoRecovery::implts_registerDocument(const css::uno::Reference< css::frame
// SAFE -> ----------------------------------
WriteGuard aWriteLock(m_aLock);
- // create a new cache entry ... this document isnt well known.
+ // create a new cache entry ... this document isn't known.
++m_nIdPool;
aNew.ID = m_nIdPool;
LOG_ASSERT(m_nIdPool>=0, "AutoRecovery::implts_registerDocument()\nOverflow of ID pool detected.")
@@ -1831,7 +1921,6 @@ void AutoRecovery::implts_markDocumentModifiedAgainstLastBackup(const css::uno::
if (pIt != m_lDocCache.end())
{
AutoRecovery::TDocumentInfo& rInfo = *pIt;
- rInfo.DocumentState |= AutoRecovery::E_MODIFIED_SINCE_LAST_AUTOSAVE;
/* Now we know, that this document was modified again and must be saved next time.
But we dont need this information for every e.g. key input of the user.
@@ -1846,7 +1935,7 @@ void AutoRecovery::implts_markDocumentModifiedAgainstLastBackup(const css::uno::
}
//-----------------------------------------------
-void AutoRecovery::implts_actualizeModifiedState(const css::uno::Reference< css::frame::XModel >& xDocument)
+void AutoRecovery::implts_updateModifiedState(const css::uno::Reference< css::frame::XModel >& xDocument)
{
CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
@@ -1866,12 +1955,10 @@ void AutoRecovery::implts_actualizeModifiedState(const css::uno::Reference< css:
if (bModified)
{
rInfo.DocumentState |= AutoRecovery::E_MODIFIED;
- rInfo.DocumentState |= AutoRecovery::E_MODIFIED_SINCE_LAST_AUTOSAVE;
}
else
{
rInfo.DocumentState &= ~AutoRecovery::E_MODIFIED;
- rInfo.DocumentState &= ~AutoRecovery::E_MODIFIED_SINCE_LAST_AUTOSAVE;
}
}
@@ -1964,6 +2051,33 @@ AutoRecovery::TDocumentList::iterator AutoRecovery::impl_searchDocument( Au
}
//-----------------------------------------------
+namespace
+{
+ void lcl_changeVisibility( const css::uno::Reference< css::frame::XFramesSupplier >& i_rFrames, sal_Bool i_bVisible )
+ {
+ css::uno::Reference< css::container::XIndexAccess > xFramesContainer( i_rFrames->getFrames(), css::uno::UNO_QUERY );
+ const sal_Int32 count = xFramesContainer->getCount();
+
+ Any aElement;
+ for ( sal_Int32 i=0; i < count; ++i )
+ {
+ aElement = xFramesContainer->getByIndex(i);
+ // check for sub frames
+ css::uno::Reference< css::frame::XFramesSupplier > xFramesSupp( aElement, css::uno::UNO_QUERY );
+ if ( xFramesSupp.is() )
+ lcl_changeVisibility( xFramesSupp, i_bVisible );
+
+ css::uno::Reference< css::frame::XFrame > xFrame( aElement, css::uno::UNO_QUERY );
+ if ( !xFrame.is() )
+ continue;
+
+ css::uno::Reference< css::awt::XWindow > xWindow( xFrame->getContainerWindow(), UNO_SET_THROW );
+ xWindow->setVisible( i_bVisible );
+ }
+ }
+}
+
+//-----------------------------------------------
void AutoRecovery::implts_changeAllDocVisibility(sal_Bool bVisible)
{
// SAFE -> ----------------------------------
@@ -1972,22 +2086,8 @@ void AutoRecovery::implts_changeAllDocVisibility(sal_Bool bVisible)
aReadLock.unlock();
// <- SAFE ----------------------------------
- css::uno::Reference< css::frame::XFramesSupplier > xDesktop (xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY);
- css::uno::Reference< css::container::XIndexAccess > xContainer(xDesktop->getFrames() , css::uno::UNO_QUERY);
- sal_Int32 c = xContainer->getCount();
- sal_Int32 i = 0;
-
- for (i=0; i<c; ++i)
- {
- css::uno::Reference< css::frame::XFrame > xTask;
-
- xContainer->getByIndex(i) >>= xTask;
- if (!xTask.is())
- continue;
-
- css::uno::Reference< css::awt::XWindow > xWindow = xTask->getContainerWindow();
- xWindow->setVisible(bVisible);
- }
+ css::uno::Reference< css::frame::XFramesSupplier > xDesktop(xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY);
+ lcl_changeVisibility( xDesktop, bVisible );
aReadLock.unlock();
// <- SAFE ----------------------------------
@@ -2180,15 +2280,15 @@ AutoRecovery::ETimerType AutoRecovery::implts_saveDocs( sal_Bool bAl
continue;
// already auto saved during this session :-)
- // This state must be reseted for all documents
+ // This state must be reset for all documents
// if timer is started with normnal AutoSaveTimerIntervall!
if ((aInfo.DocumentState & AutoRecovery::E_HANDLED) == AutoRecovery::E_HANDLED)
continue;
// Not modified documents are not saved.
// We safe an information about the URL only!
- sal_Bool bModified = ((aInfo.DocumentState & AutoRecovery::E_MODIFIED_SINCE_LAST_AUTOSAVE ) == AutoRecovery::E_MODIFIED_SINCE_LAST_AUTOSAVE);
- if (! bModified)
+ Reference< XDocumentRecovery > xDocRecover( aInfo.Document, UNO_QUERY_THROW );
+ if ( !xDocRecover->wasModifiedSinceLastSave() )
{
aInfo.DocumentState |= AutoRecovery::E_HANDLED;
continue;
@@ -2333,7 +2433,7 @@ void AutoRecovery::implts_saveOneDoc(const ::rtl::OUString&
// try to save this document as a new temp file everytimes.
// Mark AutoSave state as "INCOMPLETE" if it failed.
// Because the last temp file is to old and does not include all changes.
- css::uno::Reference< css::frame::XStorable > xStore(rInfo.Document, css::uno::UNO_QUERY_THROW);
+ Reference< XDocumentRecovery > xDocRecover(rInfo.Document, css::uno::UNO_QUERY_THROW);
// safe the state about "trying to save"
// ... we need it for recovery if e.g. a crash occures inside next line!
@@ -2346,7 +2446,7 @@ void AutoRecovery::implts_saveOneDoc(const ::rtl::OUString&
{
try
{
- xStore->storeToURL(rInfo.NewTempURL, lNewArgs.getAsConstPropertyValueList());
+ xDocRecover->storeToRecoveryFile( rInfo.NewTempURL, lNewArgs.getAsConstPropertyValueList() );
#ifdef TRIGGER_FULL_DISC_CHECK
throw css::uno::Exception();
@@ -2390,7 +2490,6 @@ void AutoRecovery::implts_saveOneDoc(const ::rtl::OUString&
rInfo.DocumentState &= ~AutoRecovery::E_TRY_SAVE;
rInfo.DocumentState |= AutoRecovery::E_HANDLED;
rInfo.DocumentState |= AutoRecovery::E_SUCCEDED;
- rInfo.DocumentState &= ~AutoRecovery::E_MODIFIED_SINCE_LAST_AUTOSAVE;
}
else
{
@@ -2466,6 +2565,9 @@ AutoRecovery::ETimerType AutoRecovery::implts_openDocs(const DispatchParams& aPa
lDescriptor[::comphelper::MediaDescriptor::PROP_REFERRER()] <<= REFERRER_USER;
lDescriptor[::comphelper::MediaDescriptor::PROP_SALVAGEDFILE()] <<= ::rtl::OUString();
+ // recovered documents are loaded hidden, and shown all at once, later
+ lDescriptor[::comphelper::MediaDescriptor::PROP_HIDDEN()] <<= true;
+
if (aParams.m_xProgress.is())
lDescriptor[::comphelper::MediaDescriptor::PROP_STATUSINDICATOR()] <<= aParams.m_xProgress;
@@ -2531,6 +2633,8 @@ AutoRecovery::ETimerType AutoRecovery::implts_openDocs(const DispatchParams& aPa
else
continue; // TODO ERROR!
+ LoadEnv::initializeUIDefaults( m_xSMGR, lDescriptor, true, NULL );
+
// <- SAFE ------------------------------
aWriteLock.unlock();
@@ -2571,12 +2675,18 @@ AutoRecovery::ETimerType AutoRecovery::implts_openDocs(const DispatchParams& aPa
{
::comphelper::MediaDescriptor lPatchDescriptor(rInfo.Document->getArgs());
lPatchDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= rInfo.RealFilter;
- rInfo.Document->attachResource(sURL, lPatchDescriptor.getAsConstPropertyValueList());
+ rInfo.Document->attachResource(rInfo.Document->getURL(), lPatchDescriptor.getAsConstPropertyValueList());
+ // do *not* use sURL here. In case this points to the recovery file, it has already been passed
+ // to recoverFromFile. Also, passing it here is logically wrong, as attachResource is intended
+ // to take the logical file URL.
}
css::uno::Reference< css::util::XModifiable > xModify(rInfo.Document, css::uno::UNO_QUERY);
- sal_Bool bModified = ((rInfo.DocumentState & AutoRecovery::E_MODIFIED) == AutoRecovery::E_MODIFIED);
- xModify->setModified(bModified);
+ if ( xModify.is() )
+ {
+ sal_Bool bModified = ((rInfo.DocumentState & AutoRecovery::E_MODIFIED) == AutoRecovery::E_MODIFIED);
+ xModify->setModified(bModified);
+ }
rInfo.DocumentState &= ~AutoRecovery::E_TRY_LOAD_BACKUP;
rInfo.DocumentState &= ~AutoRecovery::E_TRY_LOAD_ORIGINAL;
@@ -2589,8 +2699,8 @@ AutoRecovery::ETimerType AutoRecovery::implts_openDocs(const DispatchParams& aPa
/* Normaly we listen as XModifyListener on a document to know if a document was changed
since our last AutoSave. And we deregister us in case we know this state.
- But directly after one documentw as recovered ... we must start listening.
- Otherwhise the first "modify" dont reach us. Because weself called setModified()
+ But directly after one document as recovered ... we must start listening.
+ Otherwhise the first "modify" doesnt reach us. Because we ourself called setModified()
on the document via API. And currently we dont listen for any events (not at the GlobalEventBroadcaster
nor at any document!).
*/
@@ -2618,60 +2728,113 @@ void AutoRecovery::implts_openOneDoc(const ::rtl::OUString& sURL
aReadLock.unlock();
// <- SAFE ----------------------------------
- css::uno::Reference< css::util::XURLTransformer > xParser(xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY_THROW);
- css::util::URL aURL;
- aURL.Complete = sURL;
- xParser->parseStrict(aURL);
-
- LoadDispatchListener* pLoadListener = new LoadDispatchListener();
- css::uno::Reference< css::frame::XDispatchResultListener > xLoadListener (static_cast< css::frame::XDispatchResultListener* >(pLoadListener), css::uno::UNO_QUERY_THROW);
-
- css::uno::Reference< css::frame::XFrame > xDesktop (xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW);
- css::uno::Reference< css::frame::XFrame > xNewTarget = xDesktop->findFrame(SPECIALTARGET_BLANK, 0);
- css::uno::Reference< css::frame::XDispatchProvider > xProvider (xNewTarget, css::uno::UNO_QUERY_THROW);
- css::uno::Reference< css::frame::XNotifyingDispatch > xDispatcher(
- xProvider->queryDispatch(aURL, SPECIALTARGET_SELF, 0),
- css::uno::UNO_QUERY_THROW);
-
- // load the document and listen for the state of this operation.
- pLoadListener->setURL(aURL.Complete);
-
- // make sure the right progress is used always.
- impl_establishProgress(rInfo, lDescriptor, xNewTarget);
+ css::uno::Reference< css::frame::XFrame > xDesktop( xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW );
+ ::std::vector< Reference< XComponent > > aCleanup;
try
{
- xDispatcher->dispatchWithNotification(
- aURL,
- lDescriptor.getAsConstPropertyValueList(),
- xLoadListener);
+ // create a new document of the desired type
+ Reference< XModel2 > xModel( xSMGR->createInstance( rInfo.FactoryService ), UNO_QUERY_THROW );
+ aCleanup.push_back( xModel.get() );
- pLoadListener->wait(0); // wait for ever!
+ // put the filter name into the descriptor - we're not going to involve any type detection, so
+ // the document might be lost without the FilterName property
+ lDescriptor[ ::comphelper::MediaDescriptor::PROP_FILTERNAME() ] <<= rInfo.RealFilter;
- css::frame::DispatchResultEvent aResult = pLoadListener->getResult();
- if (aResult.State != css::frame::DispatchResultState::SUCCESS)
+ if ( sURL == rInfo.FactoryURL )
{
- ::rtl::OUStringBuffer sMsg(256);
- sMsg.appendAscii("Recovery of \"");
- sMsg.append (aURL.Complete );
- sMsg.appendAscii("\" failed." );
- throw css::uno::Exception(sMsg.makeStringAndClear(), static_cast< css::frame::XDispatch* >(this));
+ // if the document was a new, unmodified document, then there's nothing to recover, just to init
+ ENSURE_OR_THROW( ( rInfo.DocumentState & AutoRecovery::E_MODIFIED ) == 0,
+ "unexpected document state" );
+ Reference< XLoadable > xModelLoad( xModel, UNO_QUERY_THROW );
+ xModelLoad->initNew();
+
+ // TODO: remove load-process specific arguments from the descriptor, e.g. the status indicator
+ xModel->attachResource( sURL, lDescriptor.getAsConstPropertyValueList() );
}
+ else
+ {
+ // let it recover itself
+ Reference< XDocumentRecovery > xDocRecover( xModel, UNO_QUERY_THROW );
+ xDocRecover->recoverFromFile(
+ sURL,
+ lDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_SALVAGEDFILE(), ::rtl::OUString() ),
+ lDescriptor.getAsConstPropertyValueList()
+ );
+
+ // No attachResource needed here. By definition (of XDocumentRecovery), the implementation is responsible
+ // for completely initializing the model, which includes attachResource (or equivalent), if required.
+ }
+
+ // re-create all the views
+ ::std::vector< ::rtl::OUString > aViewsToRestore( rInfo.ViewNames.getLength() );
+ if ( rInfo.ViewNames.getLength() )
+ ::std::copy( rInfo.ViewNames.getConstArray(), rInfo.ViewNames.getConstArray() + rInfo.ViewNames.getLength(), aViewsToRestore.begin() );
+ // if we don't have views for whatever reason, then create a default-view, at least
+ if ( aViewsToRestore.empty() )
+ aViewsToRestore.push_back( ::rtl::OUString() );
+
+ for ( ::std::vector< ::rtl::OUString >::const_iterator viewName = aViewsToRestore.begin();
+ viewName != aViewsToRestore.end();
+ ++viewName
+ )
+ {
+ // create a frame
+ Reference< XFrame > xTargetFrame = xDesktop->findFrame( SPECIALTARGET_BLANK, 0 );
+ aCleanup.push_back( xTargetFrame.get() );
- rInfo.Document = fpf::extractFrameModel(xNewTarget);
+ // create a view to the document
+ Reference< XController2 > xController;
+ if ( viewName->getLength() )
+ {
+ xController.set( xModel->createViewController( *viewName, Sequence< PropertyValue >(), xTargetFrame ), UNO_SET_THROW );
+ }
+ else
+ {
+ xController.set( xModel->createDefaultViewController( xTargetFrame ), UNO_SET_THROW );
+ }
+
+ // introduce model/view/controller to each other
+ xController->attachModel( xModel.get() );
+ xModel->connectController( xController.get() );
+ xTargetFrame->setComponent( xController->getComponentWindow(), xController.get() );
+ xController->attachFrame( xTargetFrame );
+ xModel->setCurrentController( xController.get() );
+ }
+
+ rInfo.Document = xModel.get();
}
catch(const css::uno::RuntimeException&)
{ throw; }
catch(const css::uno::Exception&)
{
- css::uno::Reference< css::util::XCloseable > xClose(xNewTarget, css::uno::UNO_QUERY);
- xClose->close(sal_True);
- xNewTarget.clear();
- throw;
- }
+ Any aCaughtException( ::cppu::getCaughtException() );
+
+ // clean up
+ for ( ::std::vector< Reference< XComponent > >::const_iterator component = aCleanup.begin();
+ component != aCleanup.end();
+ ++component
+ )
+ {
+ css::uno::Reference< css::util::XCloseable > xClose( *component, css::uno::UNO_QUERY );
+ if ( xClose.is() )
+ xClose->close( sal_True );
+ else
+ (*component)->dispose();
+ }
+
+ // re-throw
+ ::rtl::OUStringBuffer sMsg(256);
+ sMsg.appendAscii("Recovery of \"");
+ sMsg.append (sURL );
+ sMsg.appendAscii("\" failed." );
- // of course we must forget all references to this temp(!) progress
- impl_forgetProgress(rInfo, lDescriptor, xNewTarget);
+ throw css::lang::WrappedTargetException(
+ sMsg.makeStringAndClear(),
+ static_cast< css::frame::XDispatch* >(this),
+ aCaughtException
+ );
+ }
}
//-----------------------------------------------
@@ -2783,7 +2946,7 @@ void AutoRecovery::implts_informListener( sal_Int32 eJ
if ((eJob & AutoRecovery::E_AUTO_SAVE) == AutoRecovery::E_AUTO_SAVE)
sFeature.append(CMD_DO_AUTO_SAVE);
#ifdef ENABLE_WARNINGS
- else
+ else if ( eJob != AutoRecovery::E_NO_JOB )
LOG_WARNING("AutoRecovery::implst_getJobDescription()", "Invalid job identifier detected.")
#endif
@@ -2842,35 +3005,18 @@ css::frame::FeatureStateEvent AutoRecovery::implst_createFeatureStateEvent(
if (sEventType.equals(OPERATION_UPDATE) && pInfo)
{
// pack rInfo for transport via UNO
- css::uno::Sequence< css::beans::NamedValue > lInfo(8);
- lInfo[0].Name = CFG_ENTRY_PROP_ID;
- lInfo[0].Value <<= pInfo->ID;
-
- lInfo[1].Name = CFG_ENTRY_PROP_ORIGINALURL;
- lInfo[1].Value <<= pInfo->OrgURL;
-
- lInfo[2].Name = CFG_ENTRY_PROP_FACTORYURL;
- lInfo[2].Value <<= pInfo->FactoryURL;
-
- lInfo[3].Name = CFG_ENTRY_PROP_TEMPLATEURL;
- lInfo[3].Value <<= pInfo->TemplateURL;
-
- lInfo[4].Name = CFG_ENTRY_PROP_TEMPURL;
- if (pInfo->OldTempURL.getLength())
- lInfo[4].Value <<= pInfo->OldTempURL;
- else
- lInfo[4].Value <<= pInfo->NewTempURL;
-
- lInfo[5].Name = CFG_ENTRY_PROP_MODULE;
- lInfo[5].Value <<= pInfo->AppModule;
-
- lInfo[6].Name = CFG_ENTRY_PROP_TITLE;
- lInfo[6].Value <<= pInfo->Title;
+ ::comphelper::NamedValueCollection aInfo;
+ aInfo.put( CFG_ENTRY_PROP_ID, pInfo->ID );
+ aInfo.put( CFG_ENTRY_PROP_ORIGINALURL, pInfo->OrgURL );
+ aInfo.put( CFG_ENTRY_PROP_FACTORYURL, pInfo->FactoryURL );
+ aInfo.put( CFG_ENTRY_PROP_TEMPLATEURL, pInfo->TemplateURL );
+ aInfo.put( CFG_ENTRY_PROP_TEMPURL, pInfo->OldTempURL.getLength() ? pInfo->OldTempURL : pInfo->NewTempURL );
+ aInfo.put( CFG_ENTRY_PROP_MODULE, pInfo->AppModule );
+ aInfo.put( CFG_ENTRY_PROP_TITLE, pInfo->Title );
+ aInfo.put( CFG_ENTRY_PROP_VIEWNAMES, pInfo->ViewNames );
+ aInfo.put( CFG_ENTRY_PROP_DOCUMENTSTATE, pInfo->DocumentState );
- lInfo[7].Name = CFG_ENTRY_PROP_DOCUMENTSTATE;
- lInfo[7].Value <<= pInfo->DocumentState;
-
- aEvent.State <<= lInfo;
+ aEvent.State <<= aInfo.getPropertyValues();
}
return aEvent;
@@ -2928,6 +3074,9 @@ void AutoRecovery::implts_doEmergencySave(const DispatchParams& aParams)
css::uno::makeAny(sal_True),
::comphelper::ConfigurationHelper::E_STANDARD);
+ // for all docs, store their current view/names in the configurtion
+ implts_persistAllActiveViewNames();
+
// The called method for saving documents runs
// during normal AutoSave more then once. Because
// it postpone active documents and save it later.
@@ -2995,6 +3144,9 @@ void AutoRecovery::implts_doSessionSave(const DispatchParams& aParams)
// Be sure to know all open documents realy .-)
implts_verifyCacheAgainstDesktopDocumentList();
+ // for all docs, store their current view/names in the configurtion
+ implts_persistAllActiveViewNames();
+
// The called method for saving documents runs
// during normal AutoSave more then once. Because
// it postpone active documents and save it later.