1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #ifndef __FRAMEWORK_SERVICES_AUTORECOVERY_HXX_ 25 #define __FRAMEWORK_SERVICES_AUTORECOVERY_HXX_ 26 27 //_______________________________________________ 28 // own includes 29 30 #include <threadhelp/threadhelpbase.hxx> 31 #include <macros/xinterface.hxx> 32 #include <macros/xtypeprovider.hxx> 33 #include <macros/xserviceinfo.hxx> 34 #include <general.h> 35 #include <stdtypes.h> 36 37 //_______________________________________________ 38 // interface includes 39 #include <com/sun/star/uno/XInterface.hpp> 40 #include <com/sun/star/lang/XTypeProvider.hpp> 41 #include <com/sun/star/lang/XServiceInfo.hpp> 42 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 43 #include <com/sun/star/frame/XDispatch.hpp> 44 #include <com/sun/star/container/XNameAccess.hpp> 45 #include <com/sun/star/document/XEventListener.hpp> 46 #include <com/sun/star/document/XEventBroadcaster.hpp> 47 #include <com/sun/star/frame/XModel.hpp> 48 #include <com/sun/star/util/XChangesListener.hpp> 49 #include <com/sun/star/task/XStatusIndicator.hpp> 50 #include <com/sun/star/util/XModifyListener.hpp> 51 52 //_______________________________________________ 53 // other includes 54 #include <comphelper/mediadescriptor.hxx> 55 #include <vcl/timer.hxx> 56 #include <vcl/evntpost.hxx> 57 #include <cppuhelper/interfacecontainer.hxx> 58 #include <cppuhelper/propshlp.hxx> 59 #include <cppuhelper/weak.hxx> 60 61 //_______________________________________________ 62 // definition 63 64 #ifndef css 65 namespace css = ::com::sun::star; 66 #endif 67 68 namespace framework 69 { 70 71 //--------------------------------------- 72 /** @short hold all needed informations for an asynchronous dispatch alive. 73 74 @descr Because some operations are forced to be executed asynchronously 75 (e.g. requested by our CrashSave/Recovery dialog) ... we must make sure 76 that these informations won't be set as "normal" members of our AutoRecovery 77 instance. Otherwise they can disturb our normal AutoSave-timer handling. 78 e.g. it can be unclear then, which progress has to be used for storing documents ... 79 */ 80 struct DispatchParams 81 { 82 public: 83 DispatchParams(); 84 DispatchParams(const ::comphelper::SequenceAsHashMap& lArgs , 85 const css::uno::Reference< css::uno::XInterface >& xOwner); 86 DispatchParams(const DispatchParams& rCopy); 87 ~DispatchParams(); 88 89 DispatchParams& operator=(const DispatchParams& rCopy); 90 void forget(); 91 92 public: 93 94 //--------------------------------------- 95 /** @short can be set from outside and is provided to 96 our internal started operations. 97 98 @descr Normally we use the normal status indicator 99 of the document windows to show a progress. 100 But in case we are used by any special UI, 101 it can provide its own status indicator object 102 to us - so we use it instead of the normal one. 103 */ 104 css::uno::Reference< css::task::XStatusIndicator > m_xProgress; 105 106 //--------------------------------------- 107 /** TODO document me */ 108 ::rtl::OUString m_sSavePath; 109 110 //--------------------------------------- 111 /** @short define the current cache entry, which should be used for current 112 backup or cleanUp operation ... which is may be done asynchronous */ 113 sal_Int32 m_nWorkingEntryID; 114 115 //--------------------------------------- 116 /** @short used for asyncoperations, to prevent us from dying. 117 118 @descr If our dispatch() method was forced to start the 119 internal operation asynchronous ... we send an event 120 to start and return immediately. But we must be sure that 121 our instance live if the event callback reach us. 122 So we hold an uno reference to ourself. 123 */ 124 css::uno::Reference< css::uno::XInterface > m_xHoldRefForAsyncOpAlive; 125 }; 126 127 //_______________________________________________ 128 /** 129 implements the functionality of AutoSave and AutoRecovery 130 of documents - including features of an EmergencySave in 131 case a GPF occurs. 132 */ 133 class AutoRecovery : public css::lang::XTypeProvider 134 , public css::lang::XServiceInfo 135 , public css::frame::XDispatch 136 , public css::document::XEventListener // => css.lang.XEventListener 137 , public css::util::XChangesListener // => css.lang.XEventListener 138 , public css::util::XModifyListener // => css.lang.XEventListener 139 // attention! Must be the first base class to guarantee right initialize lock ... 140 , private ThreadHelpBase 141 , public ::cppu::OBroadcastHelper 142 , public ::cppu::OPropertySetHelper // => XPropertySet, XFastPropertySet, XMultiPropertySet 143 , public ::cppu::OWeakObject 144 { 145 //___________________________________________ 146 // types 147 148 public: 149 150 /** These values are used as flags and represent the current state of a document. 151 Every state of the life time of a document has to be recognized here. 152 153 @attention Do not change (means reorganize) already used numbers. 154 There exists some code inside SVX, which uses the same numbers, 155 to analyze such document states. 156 Not the best design ... but may be it will be changed later .-) 157 */ 158 enum EDocStates 159 { 160 /* TEMP STATES */ 161 162 /// default state, if a document was new created or loaded 163 E_UNKNOWN = 0, 164 /// modified against the original file 165 E_MODIFIED = 1, 166 /// an active document can be postponed to be saved later. 167 E_POSTPONED = 2, 168 /// was already handled during one AutoSave/Recovery session. 169 E_HANDLED = 4, 170 /** an action was started (saving/loading) ... Can be interesting later if the process may be was interrupted by an exception. */ 171 E_TRY_SAVE = 8, 172 E_TRY_LOAD_BACKUP = 16, 173 E_TRY_LOAD_ORIGINAL = 32, 174 175 /* FINAL STATES */ 176 177 /// the Auto/Emergency saved document isn't useable any longer 178 E_DAMAGED = 64, 179 /// the Auto/Emergency saved document isn't really up-to-date (some changes can be missing) 180 E_INCOMPLETE = 128, 181 /// the Auto/Emergency saved document was processed successfully 182 E_SUCCEDED = 512 183 }; 184 185 /** @short indicates the results of a FAILURE_SAFE operation 186 187 @descr We must know, which reason was the real one in case 188 we couldn't copy a "failure document" to a user specified path. 189 We must know, if we can forget our cache entry or not. 190 */ 191 enum EFailureSafeResult 192 { 193 E_COPIED, 194 E_ORIGINAL_FILE_MISSING, 195 E_WRONG_TARGET_PATH 196 }; 197 198 // TODO document me 199 enum ETimerType 200 { 201 /** the timer shouldn't be used next time */ 202 E_DONT_START_TIMER, 203 /** timer (was/must be) started with normal AutoSaveTimeIntervall */ 204 E_NORMAL_AUTOSAVE_INTERVALL, 205 /** timer must be started with special short time intervall, 206 to poll for an user idle period */ 207 E_POLL_FOR_USER_IDLE, 208 /** timer mst be started with a very(!) short time intervall, 209 to poll for the end of an user action, which does not allow saving documents in general */ 210 E_POLL_TILL_AUTOSAVE_IS_ALLOWED, 211 /** dont start the timer - but calls the same action then before immediately again! */ 212 E_CALL_ME_BACK 213 }; 214 215 // TODO document me ... flag field 216 // Emergency_Save and Recovery overwrites Auto_Save! 217 enum EJob 218 { 219 E_NO_JOB = 0, 220 E_AUTO_SAVE = 1, 221 E_EMERGENCY_SAVE = 2, 222 E_RECOVERY = 4, 223 E_ENTRY_BACKUP = 8, 224 E_ENTRY_CLEANUP = 16, 225 E_PREPARE_EMERGENCY_SAVE = 32, 226 E_SESSION_SAVE = 64, 227 E_SESSION_RESTORE = 128, 228 E_DISABLE_AUTORECOVERY = 256, 229 E_SET_AUTOSAVE_STATE = 512, 230 E_SESSION_QUIET_QUIT = 1024 231 }; 232 233 //--------------------------------------- 234 /** @short combine different informations about one office document. */ 235 struct TDocumentInfo 236 { 237 public: 238 239 //------------------------------- TDocumentInfoframework::AutoRecovery::TDocumentInfo240 TDocumentInfo() 241 : DocumentState (E_UNKNOWN) 242 , UsedForSaving (sal_False) 243 , ListenForModify (sal_False) 244 , IgnoreClosing (sal_False) 245 , ID (-1 ) 246 {} 247 248 //------------------------------- 249 /** @short points to the document. */ 250 css::uno::Reference< css::frame::XModel > Document; 251 252 //------------------------------- 253 /** @short knows, if the document is really modified since the last autosave, 254 or was postponed, because it was an active one etcpp... 255 256 @descr Because we have no CHANGE TRACKING mechanism, based on office document, 257 we implement it by ourself. We listen for MODIFIED events 258 of each document and update this state flag here. 259 260 Further we postpone saving of active documents, e.g. if the user 261 works currently on it. We wait for an idle period then ... 262 */ 263 sal_Int32 DocumentState; 264 265 //------------------------------- 266 /** Because our applications not ready for concurrent save requests at the same time, 267 we have suppress our own AutoSave for the moment, a document will be already saved 268 by others. 269 */ 270 sal_Bool UsedForSaving; 271 272 //------------------------------- 273 /** For every user action, which modifies a document (e.g. key input) we get 274 a notification as XModifyListener. That seems to be a "performance issue" .-) 275 So we decided to listen for such modify events only for the time in which the document 276 was stored as temp. file and was not modified again by the user. 277 */ 278 sal_Bool ListenForModify; 279 280 //------------------------------- 281 /** For SessionSave we must close all open documents by ourself. 282 But because we are listen for documents events, we get some ... 283 and deregister these documents from our configuration. 284 That's why we mark these documents as "Closed by ourself" so we can 285 ignore these "OnUnload" or disposing() events .-) 286 */ 287 sal_Bool IgnoreClosing; 288 289 //------------------------------- 290 /** TODO: document me */ 291 ::rtl::OUString OrgURL; 292 ::rtl::OUString FactoryURL; 293 ::rtl::OUString TemplateURL; 294 295 ::rtl::OUString OldTempURL; 296 ::rtl::OUString NewTempURL; 297 298 ::rtl::OUString AppModule; // e.g. com.sun.star.text.TextDocument - used to identify app module 299 ::rtl::OUString FactoryService; // the service to create a document of the module 300 ::rtl::OUString RealFilter; // real filter, which was used at loading time 301 ::rtl::OUString DefaultFilter; // supports saving of the default format without losing data 302 ::rtl::OUString Extension; // file extension of the default filter 303 ::rtl::OUString Title; // can be used as "DisplayName" on every recovery UI! 304 ::com::sun::star::uno::Sequence< ::rtl::OUString > 305 ViewNames; // names of the view which were active at emergency-save time 306 307 sal_Int32 ID; 308 }; 309 310 //--------------------------------------- 311 /** @short used to know every currently open document. */ 312 typedef ::std::vector< TDocumentInfo > TDocumentList; 313 314 //___________________________________________ 315 // member 316 317 private: 318 319 //--------------------------------------- 320 /** @short the global uno service manager. 321 @descr Must be used to create own needed services. 322 */ 323 css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR; 324 325 //--------------------------------------- 326 /** @short points to the underlying recovery configuration. 327 @descr This instance does not cache - it calls directly the 328 configuration API! 329 */ 330 css::uno::Reference< css::container::XNameAccess > m_xRecoveryCFG; 331 332 //--------------------------------------- 333 /** @short points to the used configuration package or.openoffice.Setup 334 @descr This instance does not cache - it calls directly the 335 configuration API! 336 */ 337 css::uno::Reference< css::container::XNameAccess > m_xModuleCFG; 338 339 //--------------------------------------- 340 /** @short holds the global event broadcaster alive, 341 where we listen for new created documents. 342 */ 343 css::uno::Reference< css::document::XEventBroadcaster > m_xNewDocBroadcaster; 344 345 //--------------------------------------- 346 /** @short because we stop/restart listening sometimes, it's a good idea to know 347 if we already registered as listener .-) 348 */ 349 sal_Bool m_bListenForDocEvents; 350 sal_Bool m_bListenForConfigChanges; 351 352 //--------------------------------------- 353 /** @short specify the time intervall between two save actions. 354 @descr Time is measured in [min]. 355 */ 356 sal_Int32 m_nAutoSaveTimeIntervall; 357 358 //--------------------------------------- 359 /** @short for an asynchronous operation we must know, if there is 360 at least one running job (may be asynchronous!). 361 */ 362 sal_Int32 m_eJob; 363 364 //--------------------------------------- 365 /** @short the timer, which is used to be informed about the next 366 saving time ... 367 */ 368 Timer m_aTimer; 369 370 //--------------------------------------- 371 /** @short make our dispatch asynchronous ... if required to do so! */ 372 ::vcl::EventPoster m_aAsyncDispatcher; 373 374 //--------------------------------------- 375 /** @see DispatchParams 376 */ 377 DispatchParams m_aDispatchParams; 378 379 //--------------------------------------- 380 /** @short indicates, which time period is currently used by the 381 internal timer. 382 */ 383 ETimerType m_eTimerType; 384 385 //--------------------------------------- 386 /** @short this cache is used to hold all informations about 387 recovery/emergency save documents alive. 388 */ 389 TDocumentList m_lDocCache; 390 391 //--------------------------------------- 392 // TODO document me 393 sal_Int32 m_nIdPool; 394 395 //--------------------------------------- 396 /** @short contains all status listener registered at this instance. 397 */ 398 ListenerHash m_lListener; 399 400 /** @descr This member is used to prevent us against re-entrance problems. 401 A mutex can't help to prevent us from concurrent using of members 402 inside the same thread. But e.g. our internally used stl structures 403 are not threadsafe ... and furthermore they can't be used at the same time 404 for iteration and add/remove requests! 405 So we have to detect such states and ... show a warning. 406 May be there will be a better solution next time ... (copying the cache temp. 407 before using). 408 409 And further it's not possible to use a simple boolean value here. 410 Because if more than one operation iterates over the same stl container ... 411 (only to modify its elements but don't add new or remove existing ones!) 412 it should be possible doing so. But we must guarantee that the last operation resets 413 this lock ... not the first one ! So we use a "ref count" mechanism for that." 414 */ 415 sal_Int32 m_nDocCacheLock; 416 417 /** @descr These members are used to check the minimum disc space, which must exists 418 to start the corresponding operation. 419 */ 420 sal_Int32 m_nMinSpaceDocSave; 421 sal_Int32 m_nMinSpaceConfigSave; 422 423 //--------------------------------------- 424 /** @short special debug option to make testing faster. 425 426 @descr We don't interpret the timer unit as [min] ... 427 we use [ms] instead of that. Further we don't 428 wait 10 s for user idle ... 429 */ 430 #if OSL_DEBUG_LEVEL > 1 431 sal_Bool m_dbg_bMakeItFaster; 432 #endif 433 434 //--------------------------------------- 435 // HACK ... TODO 436 css::uno::Reference< css::task::XStatusIndicator > m_xExternalProgress; 437 438 //___________________________________________ 439 // interface 440 441 public: 442 443 AutoRecovery(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR); 444 virtual ~AutoRecovery( ); 445 446 // XInterface, XTypeProvider, XServiceInfo 447 FWK_DECLARE_XINTERFACE 448 FWK_DECLARE_XTYPEPROVIDER 449 DECLARE_XSERVICEINFO 450 451 //--------------------------------------- 452 // css.frame.XDispatch 453 virtual void SAL_CALL dispatch(const css::util::URL& aURL , 454 const css::uno::Sequence< css::beans::PropertyValue >& lArguments); 455 456 virtual void SAL_CALL addStatusListener(const css::uno::Reference< css::frame::XStatusListener >& xListener, 457 const css::util::URL& aURL ); 458 459 virtual void SAL_CALL removeStatusListener(const css::uno::Reference< css::frame::XStatusListener >& xListener, 460 const css::util::URL& aURL ); 461 462 //--------------------------------------- 463 // css.document.XEventListener 464 /** @short informs about created/opened documents. 465 466 @descr Every new opened/created document will be saved internally 467 so it can be checked if it's modified. This modified state 468 is used later to decide, if it must be saved or not. 469 470 @param aEvent 471 points to the new created/opened document. 472 */ 473 virtual void SAL_CALL notifyEvent(const css::document::EventObject& aEvent); 474 475 //--------------------------------------- 476 // css.util.XChangesListener 477 virtual void SAL_CALL changesOccurred(const css::util::ChangesEvent& aEvent); 478 479 //--------------------------------------- 480 // css.util.XModifyListener 481 virtual void SAL_CALL modified(const css::lang::EventObject& aEvent); 482 483 //--------------------------------------- 484 // css.lang.XEventListener 485 using cppu::OPropertySetHelper::disposing; 486 virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent); 487 488 //___________________________________________ 489 // helper 490 491 protected: 492 493 //--------------------------------------- 494 // OPropertySetHelper 495 496 virtual sal_Bool SAL_CALL convertFastPropertyValue( css::uno::Any& aConvertedValue, 497 css::uno::Any& aOldValue , 498 sal_Int32 nHandle , 499 const css::uno::Any& aValue ); 500 501 virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, 502 const css::uno::Any& aValue ); 503 using cppu::OPropertySetHelper::getFastPropertyValue; 504 virtual void SAL_CALL getFastPropertyValue(css::uno::Any& aValue , 505 sal_Int32 nHandle) const; 506 507 virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); 508 509 virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(); 510 //___________________________________________ 511 // helper 512 513 private: 514 515 //--------------------------------------- 516 /** @short open the underlying configuration. 517 518 @descr This method must be called every time 519 a configuration call is needed. Because 520 method works together with the member 521 m_xCFG, open it on demand and cache it 522 afterwards. 523 524 @return [com.sun.star.container.XNameAccess] 525 the configuration object 526 527 @throw [com.sun.star.uno.RuntimeException] 528 if config could not be opened successfully! 529 530 @threadsafe 531 */ 532 css::uno::Reference< css::container::XNameAccess > implts_openConfig(); 533 534 //--------------------------------------- 535 /** @short read the underlying configuration. 536 537 @descr After that we know the initial state - means: 538 - if AutoSave was enabled by the user 539 - which time intervall has to be used 540 - which recovery entries may already exist 541 542 @throw [com.sun.star.uno.RuntimeException] 543 if config could not be opened or read successfully! 544 545 @threadsafe 546 */ 547 void implts_readConfig(); 548 549 //--------------------------------------- 550 /** @short read the underlying configuration... 551 552 @descr ... but only keys related to the AutoSave mechanism. 553 Means: State and Timer intervall. 554 E.g. the recovery list isn't addressed here. 555 556 @throw [com.sun.star.uno.RuntimeException] 557 if config could not be opened or readed successfully! 558 559 @threadsafe 560 */ 561 void implts_readAutoSaveConfig(); 562 563 //--------------------------------------- 564 // TODO document me 565 void implts_flushConfigItem(const AutoRecovery::TDocumentInfo& rInfo , 566 sal_Bool bRemoveIt = sal_False); 567 568 //--------------------------------------- 569 // TODO document me 570 void implts_startListening(); 571 void implts_startModifyListeningOnDoc(AutoRecovery::TDocumentInfo& rInfo); 572 573 //--------------------------------------- 574 // TODO document me 575 void implts_stopListening(); 576 void implts_stopModifyListeningOnDoc(AutoRecovery::TDocumentInfo& rInfo); 577 578 //--------------------------------------- 579 /** @short stops and may be(!) restarts the timer. 580 581 @descr A running timer is stopped everytimes here. 582 But starting depends from the different internal 583 timer variables (e.g. AutoSaveEnabled, AutoSaveTimeIntervall, 584 TimerType etcpp.) 585 586 @throw [com.sun.star.uno.RuntimeException] 587 if timer could not be stopped or started! 588 589 @threadsafe 590 */ 591 void implts_updateTimer(); 592 593 //--------------------------------------- 594 /** @short stop the timer. 595 596 @descr Double calls will be ignored - means we do 597 nothing here, if the timer is already disabled. 598 599 @throw [com.sun.star.uno.RuntimeException] 600 if timer could not be stopped! 601 602 @threadsafe 603 */ 604 void implts_stopTimer(); 605 606 //--------------------------------------- 607 /** @short callback of our internal timer. 608 */ 609 DECL_LINK(implts_timerExpired, void*); 610 611 //--------------------------------------- 612 /** @short makes our dispatch() method asynchronous! 613 */ 614 DECL_LINK(implts_asyncDispatch, void*); 615 616 //--------------------------------------- 617 /** @short implements the dispatch real. */ 618 void implts_dispatch(const DispatchParams& aParams); 619 620 //--------------------------------------- 621 /** @short validate new detected document and add it into the internal 622 document list. 623 624 @descr This method should be called only, if its clear that a new 625 document was opened/created during office runtime. 626 This method checks, if its a top level document (means not an embedded one). 627 Only such top level documents can be recognized by this auto save mechanism. 628 629 @param xDocument 630 the new document, which should be checked and registered. 631 632 @threadsafe 633 */ 634 void implts_registerDocument(const css::uno::Reference< css::frame::XModel >& xDocument); 635 636 //--------------------------------------- 637 /** @short remove the specified document from our internal document list. 638 639 @param xDocument 640 the new document, which should be deregistered. 641 642 @param bStopListening 643 sal_False: must be used in case this method is called within disposing() of the document, 644 where it make no sense to deregister our listener. The container dies ... 645 sal_True : must be used in case this method is used on "deregistration" of this document, where 646 we must deregister our listener .-) 647 648 @threadsafe 649 */ 650 void implts_deregisterDocument(const css::uno::Reference< css::frame::XModel >& xDocument , 651 sal_Bool bStopListening = sal_True); 652 653 //--------------------------------------- 654 // TODO document me 655 void implts_markDocumentModifiedAgainstLastBackup(const css::uno::Reference< css::frame::XModel >& xDocument); 656 657 //--------------------------------------- 658 // TODO document me 659 void implts_updateModifiedState(const css::uno::Reference< css::frame::XModel >& xDocument); 660 661 //--------------------------------------- 662 // TODO document me 663 void implts_updateDocumentUsedForSavingState(const css::uno::Reference< css::frame::XModel >& xDocument , 664 sal_Bool bSaveInProgress); 665 666 //--------------------------------------- 667 // TODO document me 668 void implts_markDocumentAsSaved(const css::uno::Reference< css::frame::XModel >& xDocument); 669 670 //--------------------------------------- 671 /** @short search a document inside given list. 672 673 @param rList 674 reference to a vector, which can contain such 675 document. 676 677 @param xDocument 678 the document, which should be located inside the 679 given list. 680 681 @return [TDocumentList::iterator] 682 which points to the located document. 683 If document does not exists - its set to 684 rList.end()! 685 */ 686 static TDocumentList::iterator impl_searchDocument( AutoRecovery::TDocumentList& rList , 687 const css::uno::Reference< css::frame::XModel >& xDocument); 688 689 //--------------------------------------- 690 /** TODO document me */ 691 void implts_changeAllDocVisibility(sal_Bool bVisible); 692 void implts_prepareSessionShutdown(); 693 694 //--------------------------------------- 695 /** @short save all current opened documents to a specific 696 backup directory. 697 698 @descr Only really changed documents will be saved here. 699 700 Further this method returns a suggestion, if and how it should 701 be called again. May be some documents was not saved yet 702 and must wait for an user idle period ... 703 704 @param bAllowUserIdleLoop 705 Because this method is used for different uses cases, it must 706 know, which actions are allowed or not. 707 AUTO_SAVE => 708 If a document is the most active one, saving it 709 will be postponed if there exists other unsaved 710 documents. This feature was implemented, because 711 we don't wish to disturb the user on its work. 712 ... bAllowUserIdleLoop should be set to sal_True 713 EMERGENCY_SAVE / SESSION_SAVE => 714 Here we must finish our work ASAP! It's not allowed 715 to postpone any document. 716 ... bAllowUserIdleLoop must(!) be set to sal_False 717 718 @param pParams 719 sometimes this method is required inside an external dispatch request. 720 It contains some special environment variables, which overwrites 721 our normal environment. 722 AutoSave => pParams == 0 723 SessionSave/CrashSave => pParams != 0 724 725 @return A suggestion, how the timer (if it's not already disabled!) 726 should be restarted to fulfill the requirements. 727 728 @threadsafe 729 */ 730 AutoRecovery::ETimerType implts_saveDocs( sal_Bool bAllowUserIdleLoop, 731 sal_Bool bRemoveLockFiles, 732 const DispatchParams* pParams = 0); 733 734 //--------------------------------------- 735 /** @short save one of the current documents to a specific 736 backup directory. 737 738 @descr It: 739 - defines a new(!) unique temp file name 740 - save the new temp file 741 - remove the old temp file 742 - patch the given info struct 743 - and return errors. 744 745 It does not: 746 - patch the configuration. 747 748 Note further: It paches the info struct 749 more than once. E.g. the new temp URL is set 750 before the file is saved. And the old URL is removed 751 only if removing of the old file was successfully. 752 If this method returns without an exception - everything 753 was OK. Otherwise the info struct can be analyzed to 754 get more information, e.g. when the problem occurs. 755 756 @param sBackupPath 757 the base path for saving such temp files. 758 759 @param rInfo 760 points to an informations structure, where 761 e.g. the document, its modified state, the count 762 of autosave-retries etcpp. exists. 763 It's used also to return the new temp file name 764 and some other state values! 765 766 @threadsafe 767 */ 768 void implts_saveOneDoc(const ::rtl::OUString& sBackupPath , 769 AutoRecovery::TDocumentInfo& rInfo , 770 const css::uno::Reference< css::task::XStatusIndicator >& xExternalProgress); 771 772 //--------------------------------------- 773 /** @short recovery all documents, which was saved during 774 a crash before. 775 776 @return A suggestion, how this method must be called back! 777 778 @threadsafe 779 */ 780 AutoRecovery::ETimerType implts_openDocs(const DispatchParams& aParams); 781 782 //--------------------------------------- 783 // TODO document me 784 void implts_openOneDoc(const ::rtl::OUString& sURL , 785 ::comphelper::MediaDescriptor& lDescriptor, 786 AutoRecovery::TDocumentInfo& rInfo ); 787 788 //--------------------------------------- 789 // TODO document me 790 void implts_generateNewTempURL(const ::rtl::OUString& sBackupPath , 791 ::comphelper::MediaDescriptor& rMediaDescriptor, 792 AutoRecovery::TDocumentInfo& rInfo ); 793 794 //--------------------------------------- 795 /** @short notifies all interested listener about the current state 796 of the currently running operation. 797 798 @descr We support different sets of functions. AUTO_SAVE, EMERGENCY_SAVE, 799 AUTO_RECOVERY, FAILURE_SAVE ... etcpp. 800 Listener can register itself for any type of supported 801 functionality ... but not for document URL's in special. 802 803 @param eJob 804 is used to know, which set of listener we must notify. 805 806 @param aEvent 807 describe the event more in detail. 808 809 @threadsafe 810 */ 811 void implts_informListener( sal_Int32 eJob , 812 const css::frame::FeatureStateEvent& aEvent); 813 814 //--------------------------------------- 815 /** short create a feature event struct, which can be send 816 to any interested listener. 817 818 @param eJob 819 describe the current running operation 820 AUTOSAVE, EMERGENCYSAVE, RECOVERY 821 822 @param sEventType 823 describe the type of this event 824 START, STOP, UPDATE 825 826 @param pInfo 827 if sOperation is an update, this parameter must be different from NULL 828 and is used to send informations regarding the current handled document. 829 830 @return [css::frame::FeatureStateEvent] 831 the event structure for sending. 832 */ 833 static css::frame::FeatureStateEvent implst_createFeatureStateEvent( sal_Int32 eJob , 834 const ::rtl::OUString& sEventType, 835 AutoRecovery::TDocumentInfo* pInfo ); 836 837 //--------------------------------------- 838 839 // TODO document me 840 void implts_resetHandleStates(sal_Bool bLoadCache); 841 842 //--------------------------------------- 843 // TODO document me 844 void implts_specifyDefaultFilterAndExtension(AutoRecovery::TDocumentInfo& rInfo); 845 846 //--------------------------------------- 847 // TODO document me 848 void implts_specifyAppModuleAndFactory(AutoRecovery::TDocumentInfo& rInfo); 849 850 /** retrieves the names of all active views of the given document 851 @param rInfo 852 the document info, whose <code>Document</code> member must not be <NULL/>. 853 */ 854 void implts_collectActiveViewNames( AutoRecovery::TDocumentInfo& rInfo ); 855 856 /** updates the configuration so that for all documents, their current view/names are stored 857 */ 858 void implts_persistAllActiveViewNames(); 859 860 //--------------------------------------- 861 // TODO document me 862 void implts_prepareEmergencySave(); 863 864 //--------------------------------------- 865 // TODO document me 866 void implts_doEmergencySave(const DispatchParams& aParams); 867 868 //--------------------------------------- 869 // TODO document me 870 void implts_doRecovery(const DispatchParams& aParams); 871 872 //--------------------------------------- 873 // TODO document me 874 void implts_doSessionSave(const DispatchParams& aParams); 875 876 //--------------------------------------- 877 // TODO document me 878 void implts_doSessionQuietQuit(const DispatchParams& aParams); 879 880 //--------------------------------------- 881 // TODO document me 882 void implts_doSessionRestore(const DispatchParams& aParams); 883 884 //--------------------------------------- 885 // TODO document me 886 void implts_backupWorkingEntry(const DispatchParams& aParams); 887 888 //--------------------------------------- 889 // TODO document me 890 void implts_cleanUpWorkingEntry(const DispatchParams& aParams); 891 892 //--------------------------------------- 893 /** try to make sure that all changed config items (not our used 894 config access only) will be flushed back to disc. 895 896 E.g. our svtools::ConfigItems() has to be flushed explicitly .-( 897 898 Note: This method can't fail. Flushing of config entries is an 899 optional feature. Errors can be ignored. 900 */ 901 void impl_flushALLConfigChanges(); 902 903 //--------------------------------------- 904 // TODO document me 905 AutoRecovery::EFailureSafeResult implts_copyFile(const ::rtl::OUString& sSource , 906 const ::rtl::OUString& sTargetPath, 907 const ::rtl::OUString& sTargetName); 908 909 //--------------------------------------- 910 /** @short converts m_eJob into a job description, which 911 can be used to inform an outside listener 912 about the current running operation 913 914 @param eJob 915 describe the current running operation 916 AUTOSAVE, EMERGENCYSAVE, RECOVERY 917 918 @return [string] 919 a suitable job description of form: 920 vnd.sun.star.autorecovery:/do... 921 */ 922 static ::rtl::OUString implst_getJobDescription(sal_Int32 eJob); 923 924 //--------------------------------------- 925 /** @short mape the given URL to an internal int representation. 926 927 @param aURL 928 the url, which describe the next starting or may be already running 929 operation. 930 931 @return [long] 932 the internal int representation 933 see enum EJob 934 */ 935 static sal_Int32 implst_classifyJob(const css::util::URL& aURL); 936 937 /// TODO 938 void implts_verifyCacheAgainstDesktopDocumentList(); 939 940 /// TODO document me 941 sal_Bool impl_enoughDiscSpace(sal_Int32 nRequiredSpace); 942 943 /// TODO document me 944 static void impl_showFullDiscError(); 945 946 //--------------------------------------- 947 /** @short try to create/use a progress and set it inside the 948 environment. 949 950 @descr The problem behind: There exist different use cases of this method. 951 a) An external progress is provided by our CrashSave or Recovery dialog. 952 b) We must create our own progress e.g. for an AutoSave 953 c) Sometimes our application filters don't use the progress 954 provided by the MediaDescriptor. They use the Frame every time to create 955 its own progress. So we implemented a HACK for these and now we set 956 an InterceptedProgress there for the time WE use this frame for loading/storing documents .-) 957 958 @param xNewFrame 959 must be set only in case WE create a new frame (e.g. for loading documents 960 on session restore or recovery). Then search for a frame using rInfo.Document must 961 be suppressed and xFrame must be preferred instead .-) 962 963 @param rInfo 964 used e.g. to find the frame corresponding to a document. 965 This frame must be used to create a new progress e.g. for an AutoSave. 966 967 @param rArgs 968 is used to set the new created progress as parameter on these set. 969 */ 970 void impl_establishProgress(const AutoRecovery::TDocumentInfo& rInfo , 971 ::comphelper::MediaDescriptor& rArgs , 972 const css::uno::Reference< css::frame::XFrame >& xNewFrame); 973 974 void impl_forgetProgress(const AutoRecovery::TDocumentInfo& rInfo , 975 ::comphelper::MediaDescriptor& rArgs , 976 const css::uno::Reference< css::frame::XFrame >& xNewFrame); 977 978 //--------------------------------------- 979 /** try to remove the specified file from disc. 980 981 Every URL supported by our UCB component can be used here. 982 Further it doesn't matter if the file really exists or not. 983 Because removing a non existent file will have the same 984 result at the end ... a non existing file .-) 985 986 On the other side removing of files from disc is an optional 987 feature. If we are not able doing so ... it's not a real problem. 988 Ok - users disc place will be smaller then ... but we should produce 989 a crash during crash save because we can't delete a temporary file only ! 990 991 @param sURL 992 the url of the file, which should be removed. 993 */ 994 static void st_impl_removeFile(const ::rtl::OUString& sURL); 995 996 //--------------------------------------- 997 /** try to remove ".lock" file from disc if office will be terminated 998 not using the official way .-) 999 1000 This method has to be handled "optional". So every error inside 1001 has to be ignored ! This method CAN'T FAIL ... it can forget something only .-) 1002 */ 1003 static void st_impl_removeLockFile(); 1004 }; 1005 1006 } // namespace framework 1007 1008 #endif // __FRAMEWORK_SERVICES_AUTORECOVERY_HXX_ 1009