Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / svx / source / dialog / docrecovery.cxx
blob10ff3a72ef1d2ab6b2b803bd6b338ad05106e3f5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_folders.h>
22 #include <sal/macros.h>
24 #include <svx/dialmgr.hxx>
25 #include <svx/dialogs.hrc>
26 #include "docrecovery.hxx"
27 #include "docrecovery.hrc"
29 #include <comphelper/processfactory.hxx>
30 #include <comphelper/sequenceashashmap.hxx>
31 #include <comphelper/string.hxx>
32 #include <svtools/imagemgr.hxx>
33 #include <vcl/xtextedt.hxx>
34 #include <vcl/settings.hxx>
35 #include <tools/urlobj.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <vcl/svapp.hxx>
38 #include <rtl/ustrbuf.hxx>
39 #include <vcl/scrbar.hxx>
41 #include <toolkit/helper/vclunohelper.hxx>
43 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
44 #include <com/sun/star/lang/XInitialization.hpp>
45 #include <com/sun/star/beans/NamedValue.hpp>
46 #include <com/sun/star/util/URL.hpp>
47 #include <com/sun/star/util/XURLTransformer.hpp>
48 #include <com/sun/star/frame/theAutoRecovery.hpp>
49 #include <com/sun/star/frame/XDispatch.hpp>
50 #include <com/sun/star/awt/XWindow.hpp>
51 #include <com/sun/star/ui/dialogs/FolderPicker.hpp>
52 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
53 #include <com/sun/star/util/URLTransformer.hpp>
54 #include <osl/file.hxx>
55 #include <osl/security.hxx>
56 #include <rtl/bootstrap.hxx>
57 #include <unotools/pathoptions.hxx>
58 #include <unotools/localfilehelper.hxx>
59 #include "svtools/treelistentry.hxx"
60 #include <officecfg/Office/Recovery.hxx>
62 namespace svx{
63 namespace DocRecovery{
65 using namespace ::rtl;
66 using namespace ::osl;
69 TabDialog4Recovery::TabDialog4Recovery(Window* pParent)
70 : TabDialog (pParent, SVX_RES( RID_SVX_TABDLG_DOCRECOVERY ))
71 , m_pActualPage(m_lTabPages.begin() )
76 TabDialog4Recovery::~TabDialog4Recovery()
78 m_lTabPages.clear();
82 void TabDialog4Recovery::addTabPage(IExtendedTabPage* pPage)
84 if (pPage)
85 m_lTabPages.push_back(pPage);
89 short TabDialog4Recovery::Execute()
91 ::SolarMutexGuard aLock;
93 Show();
94 m_pActualPage = m_lTabPages.begin();
95 while(true)
97 IExtendedTabPage* pPage = *m_pActualPage;
98 SetViewWindow(pPage);
99 pPage->Show();
100 pPage->setDefButton();
101 short nRet = pPage->execute();
102 pPage->Hide();
104 switch(nRet)
106 case DLG_RET_OK :
108 ++m_pActualPage;
109 if (m_pActualPage == m_lTabPages.end())
110 return nRet;
112 break;
114 case DLG_RET_BACK :
116 if (m_pActualPage != m_lTabPages.begin())
117 --m_pActualPage;
119 break;
121 case DLG_RET_UNKNOWN :
122 case DLG_RET_CANCEL :
123 case DLG_RET_OK_AUTOLUNCH :
124 return nRet;
130 RecoveryCore::RecoveryCore(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
131 bool bUsedForSaving)
132 : m_xContext ( rxContext )
133 , m_pListener ( 0 )
134 , m_bListenForSaving(bUsedForSaving)
136 impl_startListening();
140 RecoveryCore::~RecoveryCore()
142 impl_stopListening();
146 css::uno::Reference< css::uno::XComponentContext > RecoveryCore::getComponentContext()
148 return m_xContext;
152 TURLList* RecoveryCore::getURLListAccess()
154 return &m_lURLs;
158 bool RecoveryCore::isBrokenTempEntry(const TURLInfo& rInfo)
160 if (rInfo.TempURL.isEmpty())
161 return false;
163 // Note: If the original files was recovery ... but a temp file
164 // exists ... an error inside the temp file exists!
165 if (
166 !(rInfo.RecoveryState == E_RECOVERY_FAILED ) &&
167 !(rInfo.RecoveryState == E_ORIGINAL_DOCUMENT_RECOVERED)
169 return false;
171 return true;
175 void RecoveryCore::saveBrokenTempEntries(const OUString& rPath)
177 if (rPath.isEmpty())
178 return;
180 if (!m_xRealCore.is())
181 return;
183 // prepare all needed parameters for the following dispatch() request.
184 css::util::URL aCopyURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_BACKUP);
185 css::uno::Sequence< css::beans::PropertyValue > lCopyArgs(3);
186 lCopyArgs[0].Name = PROP_DISPATCHASYNCHRON;
187 lCopyArgs[0].Value <<= sal_False;
188 lCopyArgs[1].Name = PROP_SAVEPATH;
189 lCopyArgs[1].Value <<= rPath;
190 lCopyArgs[2].Name = PROP_ENTRYID;
191 // lCopyArgs[2].Value will be changed during next loop ...
193 // work on a copied list only ...
194 // Reason: We will get notifications from the core for every
195 // changed or removed element. And that will change our m_lURLs list.
196 // That's not a good idea, if we use a stl iterator inbetween .-)
197 TURLList lURLs = m_lURLs;
198 TURLList::const_iterator pIt;
199 for ( pIt = lURLs.begin();
200 pIt != lURLs.end() ;
201 ++pIt )
203 const TURLInfo& rInfo = *pIt;
204 if (!RecoveryCore::isBrokenTempEntry(rInfo))
205 continue;
207 lCopyArgs[2].Value <<= rInfo.ID;
208 m_xRealCore->dispatch(aCopyURL, lCopyArgs);
213 void RecoveryCore::saveAllTempEntries(const OUString& rPath)
215 if (rPath.isEmpty())
216 return;
218 if (!m_xRealCore.is())
219 return;
221 // prepare all needed parameters for the following dispatch() request.
222 css::util::URL aCopyURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_BACKUP);
223 css::uno::Sequence< css::beans::PropertyValue > lCopyArgs(3);
224 lCopyArgs[0].Name = PROP_DISPATCHASYNCHRON;
225 lCopyArgs[0].Value <<= sal_False;
226 lCopyArgs[1].Name = PROP_SAVEPATH;
227 lCopyArgs[1].Value <<= rPath;
228 lCopyArgs[2].Name = PROP_ENTRYID;
229 // lCopyArgs[2].Value will be changed during next loop ...
231 // work on a copied list only ...
232 // Reason: We will get notifications from the core for every
233 // changed or removed element. And that will change our m_lURLs list.
234 // That's not a good idea, if we use a stl iterator inbetween .-)
235 TURLList lURLs = m_lURLs;
236 TURLList::const_iterator pIt;
237 for ( pIt = lURLs.begin();
238 pIt != lURLs.end() ;
239 ++pIt )
241 const TURLInfo& rInfo = *pIt;
242 if (rInfo.TempURL.isEmpty())
243 continue;
245 lCopyArgs[2].Value <<= rInfo.ID;
246 m_xRealCore->dispatch(aCopyURL, lCopyArgs);
251 void RecoveryCore::forgetBrokenTempEntries()
253 if (!m_xRealCore.is())
254 return;
256 css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
257 css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
258 lRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
259 lRemoveArgs[0].Value <<= sal_False;
260 lRemoveArgs[1].Name = PROP_ENTRYID;
261 // lRemoveArgs[1].Value will be changed during next loop ...
263 // work on a copied list only ...
264 // Reason: We will get notifications from the core for every
265 // changed or removed element. And that will change our m_lURLs list.
266 // That's not a good idea, if we use a stl iterator inbetween .-)
267 TURLList lURLs = m_lURLs;
268 TURLList::const_iterator pIt;
269 for ( pIt = lURLs.begin();
270 pIt != lURLs.end() ;
271 ++pIt )
273 const TURLInfo& rInfo = *pIt;
274 if (!RecoveryCore::isBrokenTempEntry(rInfo))
275 continue;
277 lRemoveArgs[1].Value <<= rInfo.ID;
278 m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
283 void RecoveryCore::forgetAllRecoveryEntries()
285 if (!m_xRealCore.is())
286 return;
288 css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
289 css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
290 lRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
291 lRemoveArgs[0].Value <<= sal_False;
292 lRemoveArgs[1].Name = PROP_ENTRYID;
293 // lRemoveArgs[1].Value will be changed during next loop ...
295 // work on a copied list only ...
296 // Reason: We will get notifications from the core for every
297 // changed or removed element. And that will change our m_lURLs list.
298 // That's not a good idea, if we use a stl iterator inbetween .-)
299 TURLList lURLs = m_lURLs;
300 TURLList::const_iterator pIt;
301 for ( pIt = lURLs.begin();
302 pIt != lURLs.end() ;
303 ++pIt )
305 const TURLInfo& rInfo = *pIt;
306 lRemoveArgs[1].Value <<= rInfo.ID;
307 m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
312 void RecoveryCore::forgetBrokenRecoveryEntries()
314 if (!m_xRealCore.is())
315 return;
317 css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
318 css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
319 lRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
320 lRemoveArgs[0].Value <<= sal_False;
321 lRemoveArgs[1].Name = PROP_ENTRYID;
322 // lRemoveArgs[1].Value will be changed during next loop ...
324 // work on a copied list only ...
325 // Reason: We will get notifications from the core for every
326 // changed or removed element. And that will change our m_lURLs list.
327 // That's not a good idea, if we use a stl iterator inbetween .-)
328 TURLList lURLs = m_lURLs;
329 TURLList::const_iterator pIt;
330 for ( pIt = lURLs.begin();
331 pIt != lURLs.end() ;
332 ++pIt )
334 const TURLInfo& rInfo = *pIt;
335 if (!RecoveryCore::isBrokenTempEntry(rInfo))
336 continue;
338 lRemoveArgs[1].Value <<= rInfo.ID;
339 m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
344 void RecoveryCore::setProgressHandler(const css::uno::Reference< css::task::XStatusIndicator >& xProgress)
346 m_xProgress = xProgress;
350 void RecoveryCore::setUpdateListener(IRecoveryUpdateListener* pListener)
352 m_pListener = pListener;
356 void RecoveryCore::doEmergencySavePrepare()
358 if (!m_xRealCore.is())
359 return;
361 css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_PREPARE_EMERGENCY_SAVE);
363 css::uno::Sequence< css::beans::PropertyValue > lArgs(1);
364 lArgs[0].Name = PROP_DISPATCHASYNCHRON;
365 lArgs[0].Value <<= sal_False;
367 m_xRealCore->dispatch(aURL, lArgs);
371 void RecoveryCore::doEmergencySave()
373 if (!m_xRealCore.is())
374 return;
376 css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_EMERGENCY_SAVE);
378 css::uno::Sequence< css::beans::PropertyValue > lArgs(2);
379 lArgs[0].Name = PROP_STATUSINDICATOR;
380 lArgs[0].Value <<= m_xProgress;
381 lArgs[1].Name = PROP_DISPATCHASYNCHRON;
382 lArgs[1].Value <<= sal_True;
384 m_xRealCore->dispatch(aURL, lArgs);
388 void RecoveryCore::doRecovery()
390 if (!m_xRealCore.is())
391 return;
393 css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_RECOVERY);
395 css::uno::Sequence< css::beans::PropertyValue > lArgs(2);
396 lArgs[0].Name = PROP_STATUSINDICATOR;
397 lArgs[0].Value <<= m_xProgress;
398 lArgs[1].Name = PROP_DISPATCHASYNCHRON;
399 lArgs[1].Value <<= sal_True;
401 m_xRealCore->dispatch(aURL, lArgs);
405 ERecoveryState RecoveryCore::mapDocState2RecoverState(sal_Int32 eDocState)
407 // ???
408 ERecoveryState eRecState = E_NOT_RECOVERED_YET;
410 /* Attention:
411 Some of the following states can occur at the
412 same time. So we have to check for the "worst case" first!
414 DAMAGED -> INCOMPLETE -> HANDLED
417 // running ...
418 if (
419 ((eDocState & E_TRY_LOAD_BACKUP ) == E_TRY_LOAD_BACKUP ) ||
420 ((eDocState & E_TRY_LOAD_ORIGINAL) == E_TRY_LOAD_ORIGINAL)
422 eRecState = E_RECOVERY_IS_IN_PROGRESS;
423 // red
424 else if ((eDocState & E_DAMAGED) == E_DAMAGED)
425 eRecState = E_RECOVERY_FAILED;
426 // yellow
427 else if ((eDocState & E_INCOMPLETE) == E_INCOMPLETE)
428 eRecState = E_ORIGINAL_DOCUMENT_RECOVERED;
429 // green
430 else if ((eDocState & E_SUCCEDED) == E_SUCCEDED)
431 eRecState = E_SUCCESSFULLY_RECOVERED;
433 return eRecState;
437 void SAL_CALL RecoveryCore::statusChanged(const css::frame::FeatureStateEvent& aEvent)
438 throw(css::uno::RuntimeException, std::exception)
440 // a) special notification about start/stop async dispatch!
441 // FeatureDescriptor = "start" || "stop"
442 if (aEvent.FeatureDescriptor.equals(RECOVERY_OPERATIONSTATE_START))
444 if (m_pListener)
445 m_pListener->start();
446 return;
449 if (aEvent.FeatureDescriptor.equals(RECOVERY_OPERATIONSTATE_STOP))
451 if (m_pListener)
452 m_pListener->end();
453 return;
456 // b) normal notification about changed items
457 // FeatureDescriptor = "Update"
458 // State = Lits of information [seq< NamedValue >]
459 if (! aEvent.FeatureDescriptor.equals(RECOVERY_OPERATIONSTATE_UPDATE))
460 return;
462 ::comphelper::SequenceAsHashMap lInfo(aEvent.State);
463 TURLInfo aNew;
465 aNew.ID = lInfo.getUnpackedValueOrDefault(STATEPROP_ID , (sal_Int32)0 );
466 aNew.DocState = lInfo.getUnpackedValueOrDefault(STATEPROP_STATE , (sal_Int32)0 );
467 aNew.OrgURL = lInfo.getUnpackedValueOrDefault(STATEPROP_ORGURL , OUString());
468 aNew.TempURL = lInfo.getUnpackedValueOrDefault(STATEPROP_TEMPURL , OUString());
469 aNew.FactoryURL = lInfo.getUnpackedValueOrDefault(STATEPROP_FACTORYURL , OUString());
470 aNew.TemplateURL = lInfo.getUnpackedValueOrDefault(STATEPROP_TEMPLATEURL, OUString());
471 aNew.DisplayName = lInfo.getUnpackedValueOrDefault(STATEPROP_TITLE , OUString());
472 aNew.Module = lInfo.getUnpackedValueOrDefault(STATEPROP_MODULE , OUString());
474 // search for already existing items and update her nState value ...
475 TURLList::iterator pIt;
476 for ( pIt = m_lURLs.begin();
477 pIt != m_lURLs.end() ;
478 ++pIt )
480 TURLInfo& aOld = *pIt;
481 if (aOld.ID == aNew.ID)
483 // change existing
484 aOld.DocState = aNew.DocState;
485 aOld.RecoveryState = RecoveryCore::mapDocState2RecoverState(aOld.DocState);
486 if (m_pListener)
488 m_pListener->updateItems();
489 m_pListener->stepNext(&aOld);
491 return;
495 // append as new one
496 // TODO think about mmatching Module name to a corresponding icon
497 OUString sURL = aNew.OrgURL;
498 if (sURL.isEmpty())
499 sURL = aNew.FactoryURL;
500 if (sURL.isEmpty())
501 sURL = aNew.TempURL;
502 if (sURL.isEmpty())
503 sURL = aNew.TemplateURL;
504 INetURLObject aURL(sURL);
505 aNew.StandardImage = SvFileInformationManager::GetFileImage(aURL, false);
507 /* set the right UI state for this item to NOT_RECOVERED_YET ... because nDocState shows the state of
508 the last emergency save operation before and is interessting for the used recovery core service only ...
509 for now! But if there is a further notification for this item (see lines above!) we must
510 map the doc state to an UI state. */
511 aNew.RecoveryState = E_NOT_RECOVERED_YET;
513 // patch DisplayName! Because the document title contain more then the file name ...
514 sal_Int32 i = aNew.DisplayName.indexOf(" - ");
515 if (i > 0)
516 aNew.DisplayName = aNew.DisplayName.copy(0, i);
518 m_lURLs.push_back(aNew);
520 if (m_pListener)
521 m_pListener->updateItems();
525 void SAL_CALL RecoveryCore::disposing(const css::lang::EventObject& /*aEvent*/)
526 throw(css::uno::RuntimeException, std::exception)
528 m_xRealCore.clear();
532 void RecoveryCore::impl_startListening()
534 // listening already initialized ?
535 if (m_xRealCore.is())
536 return;
537 m_xRealCore = css::frame::theAutoRecovery::get(m_xContext);
539 css::util::URL aURL;
540 if (m_bListenForSaving)
541 aURL.Complete = RECOVERY_CMD_DO_EMERGENCY_SAVE;
542 else
543 aURL.Complete = RECOVERY_CMD_DO_RECOVERY;
544 css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
545 xParser->parseStrict(aURL);
547 /* Note: addStatusListener() call us synchronous back ... so we
548 will get the complete list of currently open documents! */
549 m_xRealCore->addStatusListener(static_cast< css::frame::XStatusListener* >(this), aURL);
553 void RecoveryCore::impl_stopListening()
555 // Ignore it, if this instance doesn't listen currently
556 if (!m_xRealCore.is())
557 return;
559 css::util::URL aURL;
560 if (m_bListenForSaving)
561 aURL.Complete = RECOVERY_CMD_DO_EMERGENCY_SAVE;
562 else
563 aURL.Complete = RECOVERY_CMD_DO_RECOVERY;
564 css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
565 xParser->parseStrict(aURL);
567 m_xRealCore->removeStatusListener(static_cast< css::frame::XStatusListener* >(this), aURL);
568 m_xRealCore.clear();
572 css::util::URL RecoveryCore::impl_getParsedURL(const OUString& sURL)
574 css::util::URL aURL;
575 aURL.Complete = sURL;
577 css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
578 xParser->parseStrict(aURL);
580 return aURL;
584 PluginProgressWindow::PluginProgressWindow( Window* pParent ,
585 const css::uno::Reference< css::lang::XComponent >& xProgress)
586 : Window (pParent )
587 , m_xProgress(xProgress)
589 Show();
590 Size aParentSize = pParent->GetSizePixel();
591 // align the progressbar to its parent
592 setPosSizePixel( -9, 0, aParentSize.Width() + 15, aParentSize.Height() - 4 );
596 PluginProgressWindow::~PluginProgressWindow()
598 if (m_xProgress.is())
599 m_xProgress->dispose();
603 PluginProgress::PluginProgress( Window* pParent,
604 const css::uno::Reference< css::uno::XComponentContext >& xContext )
606 m_pPlugProgressWindow = new PluginProgressWindow(pParent, static_cast< css::lang::XComponent* >(this));
607 css::uno::Reference< css::awt::XWindow > xProgressWindow = VCLUnoHelper::GetInterface(m_pPlugProgressWindow);
608 m_xProgressFactory = css::task::StatusIndicatorFactory::createWithWindow(xContext, xProgressWindow, sal_False/*DisableReschedule*/, sal_True/*AllowParentShow*/);
609 m_xProgress = m_xProgressFactory->createStatusIndicator();
613 PluginProgress::~PluginProgress()
618 void SAL_CALL PluginProgress::dispose()
619 throw(css::uno::RuntimeException, std::exception)
621 // m_pPluginProgressWindow was deleted ...
622 // So the internal pointer of this progress
623 // weill be dead!
624 m_xProgress.clear();
628 void SAL_CALL PluginProgress::addEventListener(const css::uno::Reference< css::lang::XEventListener >& )
629 throw(css::uno::RuntimeException, std::exception)
634 void SAL_CALL PluginProgress::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& )
635 throw(css::uno::RuntimeException, std::exception)
640 void SAL_CALL PluginProgress::start(const OUString&,
641 sal_Int32 nRange)
642 throw(css::uno::RuntimeException, std::exception)
644 if (m_xProgress.is())
645 m_xProgress->start(OUString(), nRange);
649 void SAL_CALL PluginProgress::end()
650 throw(css::uno::RuntimeException, std::exception)
652 if (m_xProgress.is())
653 m_xProgress->end();
657 void SAL_CALL PluginProgress::setText(const OUString& sText)
658 throw(css::uno::RuntimeException, std::exception)
660 if (m_xProgress.is())
661 m_xProgress->setText(sText);
665 void SAL_CALL PluginProgress::setValue(sal_Int32 nValue)
666 throw(css::uno::RuntimeException, std::exception)
668 if (m_xProgress.is())
669 m_xProgress->setValue(nValue);
673 void SAL_CALL PluginProgress::reset()
674 throw(css::uno::RuntimeException, std::exception)
676 if (m_xProgress.is())
677 m_xProgress->reset();
681 SaveDialog::SaveDialog(Window* pParent,
682 RecoveryCore* pCore )
683 : IExtendedTabPage( pParent, SVX_RES( RID_SVXPAGE_DOCRECOVERY_SAVE ) )
684 , m_aTitleFT ( this , SVX_RES ( FT_SAVE_TITLE ) )
685 , m_aTitleWin ( this , SVX_RES ( WIN_SAVE_TITLE ) )
686 , m_aTitleFL ( this , SVX_RES ( FL_SAVE_TITLE ) )
687 , m_aDescrFT ( this , SVX_RES ( FT_SAVE_DESCR ) )
688 , m_aFileListFT ( this , SVX_RES ( FT_SAVE_FILELIST ) )
689 , m_aFileListLB ( this , SVX_RES ( LB_SAVE_FILELIST ) )
690 , m_aBottomFL ( this , SVX_RES ( FL_SAVE_BOTTOM ) )
691 , m_aOkBtn ( this , SVX_RES ( BT_SAVE_OK ) )
692 , m_pCore ( pCore )
694 FreeResource();
696 // Prepare the office for the following crash save step.
697 // E.g. hide all open widows so the user can't influence our
698 // operation .-)
699 m_pCore->doEmergencySavePrepare();
701 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
702 Wallpaper aBackground(rStyleSettings.GetWindowColor());
703 m_aTitleWin.SetBackground(aBackground);
704 m_aTitleFT.SetBackground (aBackground);
706 Font aFont(m_aTitleFT.GetFont());
707 aFont.SetWeight(WEIGHT_BOLD);
708 m_aTitleFT.SetFont(aFont);
710 m_aOkBtn.SetClickHdl( LINK( this, SaveDialog, OKButtonHdl ) );
711 m_aFileListLB.SetControlBackground( rStyleSettings.GetDialogColor() );
713 // fill listbox with current open documents
714 m_aFileListLB.Clear();
716 TURLList* pURLs = m_pCore->getURLListAccess();
717 TURLList::const_iterator pIt;
719 for ( pIt = pURLs->begin();
720 pIt != pURLs->end() ;
721 ++pIt )
723 const TURLInfo& rInfo = *pIt;
724 m_aFileListLB.InsertEntry( rInfo.DisplayName, rInfo.StandardImage );
729 SaveDialog::~SaveDialog()
734 IMPL_LINK_NOARG(SaveDialog, OKButtonHdl)
736 m_nResult = DLG_RET_OK;
737 return 0;
741 short SaveDialog::execute()
743 ::SolarMutexGuard aLock;
745 // wait for user input "OK"
746 m_nResult = DLG_RET_UNKNOWN;
747 while(m_nResult == DLG_RET_UNKNOWN)
748 Application::Yield();
750 // start crash-save with progress
751 if (m_nResult == DLG_RET_OK)
753 SaveProgressDialog* pProgress = new SaveProgressDialog(this, m_pCore);
754 m_nResult = pProgress->Execute();
755 delete pProgress;
757 // if "CANCEL" => return "CANCEL"
758 // if "OK" => "AUTOLUNCH" always !
759 if (m_nResult == DLG_RET_OK)
760 m_nResult = DLG_RET_OK_AUTOLUNCH;
762 return m_nResult;
766 void SaveDialog::setDefButton()
768 m_aOkBtn.GrabFocus();
772 SaveProgressDialog::SaveProgressDialog(Window* pParent,
773 RecoveryCore* pCore )
774 : ModalDialog ( pParent , SVX_RES( RID_SVX_MDLG_DOCRECOVERY_PROGR ) )
775 , m_aHintFT ( this , SVX_RES ( FT_SAVEPROGR_HINT ) )
776 , m_aProgrFT ( this , SVX_RES ( FT_SAVEPROGR_PROGR ) )
777 , m_aProgrParent( this , SVX_RES ( WIN_SAVEPROGR_PROGR ) )
778 , m_pCore ( pCore )
780 FreeResource();
781 PluginProgress* pProgress = new PluginProgress( &m_aProgrParent, pCore->getComponentContext() );
782 m_xProgress = css::uno::Reference< css::task::XStatusIndicator >(static_cast< css::task::XStatusIndicator* >(pProgress), css::uno::UNO_QUERY_THROW);
786 SaveProgressDialog::~SaveProgressDialog()
791 short SaveProgressDialog::Execute()
793 ::SolarMutexGuard aLock;
795 m_pCore->setProgressHandler(m_xProgress);
796 m_pCore->setUpdateListener(this);
797 m_pCore->doEmergencySave();
798 short nRet = ModalDialog::Execute();
799 m_pCore->setUpdateListener(0);
800 return nRet;
804 void SaveProgressDialog::updateItems()
809 void SaveProgressDialog::stepNext(TURLInfo* )
811 /* TODO
813 wenn die m_pCore noch ein Member m_nCurrentItem haette
814 koennte man dort erkennen, wer gerade drann war, wer demnaechst
815 dran ist ... Diese Info kann man dann in unserem Progress FixText anzeigen ...
820 void SaveProgressDialog::start()
825 void SaveProgressDialog::end()
827 EndDialog(DLG_RET_OK);
831 RecovDocListEntry::RecovDocListEntry( SvTreeListEntry* pEntry,
832 sal_uInt16 nFlags,
833 const OUString& sText )
834 : SvLBoxString( pEntry, nFlags, sText )
839 void RecovDocListEntry::Paint(
840 const Point& aPos, SvTreeListBox& aDevice, const SvViewDataEntry* /*pView*/, const SvTreeListEntry* pEntry)
842 const Image* pImg = 0;
843 const OUString* pTxt = 0;
844 RecovDocList* pList = static_cast< RecovDocList* >(&aDevice);
846 TURLInfo* pInfo = (TURLInfo*)pEntry->GetUserData();
847 switch(pInfo->RecoveryState)
849 case E_SUCCESSFULLY_RECOVERED :
851 pImg = &pList->m_aGreenCheckImg;
852 pTxt = &pList->m_aSuccessRecovStr;
854 break;
856 case E_ORIGINAL_DOCUMENT_RECOVERED : // TODO must be renamed into ORIGINAL DOCUMENT recovered! Because its marked as yellow
858 pImg = &pList->m_aYellowCheckImg;
859 pTxt = &pList->m_aOrigDocRecovStr;
861 break;
863 case E_RECOVERY_FAILED :
865 pImg = &pList->m_aRedCrossImg;
866 pTxt = &pList->m_aRecovFailedStr;
868 break;
870 case E_RECOVERY_IS_IN_PROGRESS :
872 pImg = 0;
873 pTxt = &pList->m_aRecovInProgrStr;
875 break;
877 case E_NOT_RECOVERED_YET :
879 pImg = 0;
880 pTxt = &pList->m_aNotRecovYetStr;
882 break;
885 if (pImg)
886 aDevice.DrawImage(aPos, *pImg);
888 if (pTxt)
890 Point aPnt(aPos);
891 aPnt.X() += pList->m_aGreenCheckImg.GetSizePixel().Width();
892 aPnt.X() += 10;
893 aDevice.DrawText(aPnt, *pTxt);
897 RecovDocList::RecovDocList(SvSimpleTableContainer& rParent, ResMgr &rResMgr)
898 : SvSimpleTable ( rParent )
899 , m_aGreenCheckImg ( ResId(IMG_GREENCHECK, rResMgr ) )
900 , m_aYellowCheckImg ( ResId(IMG_YELLOWCHECK, rResMgr ) )
901 , m_aRedCrossImg ( ResId(IMG_REDCROSS, rResMgr ) )
902 , m_aSuccessRecovStr ( ResId(STR_SUCCESSRECOV, rResMgr ) )
903 , m_aOrigDocRecovStr ( ResId(STR_ORIGDOCRECOV, rResMgr ) )
904 , m_aRecovFailedStr ( ResId(STR_RECOVFAILED, rResMgr ) )
905 , m_aRecovInProgrStr ( ResId(STR_RECOVINPROGR, rResMgr ) )
906 , m_aNotRecovYetStr ( ResId(STR_NOTRECOVYET, rResMgr ) )
911 RecovDocList::~RecovDocList()
916 void RecovDocList::InitEntry(SvTreeListEntry* pEntry,
917 const OUString& rText,
918 const Image& rImage1,
919 const Image& rImage2,
920 SvLBoxButtonKind eButtonKind)
922 SvTabListBox::InitEntry(pEntry, rText, rImage1, rImage2, eButtonKind);
923 DBG_ASSERT( TabCount() == 2, "*RecovDocList::InitEntry(): structure missmatch" );
925 SvLBoxString* pCol = (SvLBoxString*)pEntry->GetItem(2);
926 RecovDocListEntry* p = new RecovDocListEntry(pEntry, 0, pCol->GetText());
927 pEntry->ReplaceItem(p, 2);
931 short impl_askUserForWizardCancel(Window* pParent, sal_Int16 nRes)
933 QueryBox aQuery(pParent, SVX_RES(nRes));
934 if (aQuery.Execute() == RET_YES)
935 return DLG_RET_OK;
936 else
937 return DLG_RET_CANCEL;
941 RecoveryDialog::RecoveryDialog(Window* pParent,
942 RecoveryCore* pCore )
943 : IExtendedTabPage( pParent , SVX_RES( RID_SVXPAGE_DOCRECOVERY_RECOVER ) )
944 , m_aTitleFT ( this , SVX_RES ( FT_RECOV_TITLE ) )
945 , m_aTitleWin ( this , SVX_RES ( WIN_RECOV_TITLE ) )
946 , m_aTitleFL ( this , SVX_RES ( FL_RECOV_TITLE ) )
947 , m_aDescrFT ( this , SVX_RES ( FT_RECOV_DESCR ) )
948 , m_aProgressFT ( this , SVX_RES ( FT_RECOV_PROGR ) )
949 , m_aProgrParent ( this , SVX_RES ( WIN_RECOV_PROGR ) )
950 , m_aFileListFT ( this , SVX_RES ( FT_RECOV_FILELIST ) )
951 , m_aFileListLBContainer( this , SVX_RES ( LB_RECOV_FILELIST ) )
952 , m_aFileListLB (m_aFileListLBContainer, DIALOG_MGR())
953 , m_aBottomFL ( this , SVX_RES ( FL_RECOV_BOTTOM ) )
954 , m_aNextBtn ( this , SVX_RES ( BTN_RECOV_NEXT ) )
955 , m_aCancelBtn ( this , SVX_RES ( BTN_RECOV_CANCEL ) )
956 , m_aTitleRecoveryInProgress(SVX_RESSTR(STR_RECOVERY_INPROGRESS))
957 , m_aRecoveryOnlyFinish (SVX_RESSTR(STR_RECOVERYONLY_FINISH))
958 , m_aRecoveryOnlyFinishDescr(SVX_RESSTR(STR_RECOVERYONLY_FINISH_DESCR))
959 , m_pDefButton ( NULL )
960 , m_pCore ( pCore )
961 , m_eRecoveryState (RecoveryDialog::E_RECOVERY_PREPARED)
962 , m_bWaitForUser (false)
963 , m_bWaitForCore (false)
964 , m_bUserDecideNext (false)
965 , m_bWasRecoveryStarted (false)
967 static long nTabs[] = { 2, 0, 40*RECOV_CONTROLWIDTH/100 };
968 m_aFileListLB.SetTabs( &nTabs[0] );
969 m_aFileListLB.InsertHeaderEntry(SVX_RESSTR(STR_HEADERBAR));
971 FreeResource();
973 PluginProgress* pProgress = new PluginProgress( &m_aProgrParent, pCore->getComponentContext() );
974 m_xProgress = css::uno::Reference< css::task::XStatusIndicator >(static_cast< css::task::XStatusIndicator* >(pProgress), css::uno::UNO_QUERY_THROW);
976 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
977 Wallpaper aBackground( rStyleSettings.GetWindowColor() );
978 m_aTitleWin.SetBackground(aBackground);
979 m_aTitleFT.SetBackground (aBackground);
981 Font aFont(m_aTitleFT.GetFont());
982 aFont.SetWeight(WEIGHT_BOLD);
983 m_aTitleFT.SetFont(aFont);
985 m_aFileListLB.SetBackground( rStyleSettings.GetDialogColor() );
987 m_aNextBtn.Enable(true);
988 m_aNextBtn.SetClickHdl( LINK( this, RecoveryDialog, NextButtonHdl ) );
989 m_aCancelBtn.SetClickHdl( LINK( this, RecoveryDialog, CancelButtonHdl ) );
991 // fill list box first time
992 TURLList* pURLList = m_pCore->getURLListAccess();
993 TURLList::const_iterator pIt;
994 for ( pIt = pURLList->begin();
995 pIt != pURLList->end() ;
996 ++pIt )
998 const TURLInfo& rInfo = *pIt;
1000 OUString sName( rInfo.DisplayName );
1001 sName += "\t";
1002 sName += impl_getStatusString( rInfo );
1003 SvTreeListEntry* pEntry = m_aFileListLB.InsertEntry(sName, rInfo.StandardImage, rInfo.StandardImage);
1004 pEntry->SetUserData((void*)&rInfo);
1007 // mark first item
1008 SvTreeListEntry* pFirst = m_aFileListLB.First();
1009 if (pFirst)
1010 m_aFileListLB.SetCursor(pFirst, true);
1014 RecoveryDialog::~RecoveryDialog()
1019 short RecoveryDialog::execute()
1021 ::SolarMutexGuard aSolarLock;
1023 switch(m_eRecoveryState)
1025 case RecoveryDialog::E_RECOVERY_PREPARED :
1027 // Dialog was started first time ...
1028 // wait for user decision ("start" or "cancel" recovery)
1029 // This decision will be made inside the NextBtn handler.
1030 m_aNextBtn.Enable(true);
1031 m_aCancelBtn.Enable(true);
1032 m_bWaitForUser = true;
1033 while(m_bWaitForUser)
1034 Application::Yield();
1035 if (m_bUserDecideNext)
1036 m_eRecoveryState = RecoveryDialog::E_RECOVERY_IN_PROGRESS;
1037 else
1038 m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED;
1039 return execute();
1042 case RecoveryDialog::E_RECOVERY_IN_PROGRESS :
1044 // user decided to start recovery ...
1045 m_bWasRecoveryStarted = true;
1046 // do it asynchronous (to allow repaints)
1047 // and wait for this asynchronous operation.
1048 m_aDescrFT.SetText( m_aTitleRecoveryInProgress );
1049 m_aNextBtn.Enable(false);
1050 m_aCancelBtn.Enable(false);
1051 m_pCore->setProgressHandler(m_xProgress);
1052 m_pCore->setUpdateListener(this);
1053 m_pCore->doRecovery();
1055 m_bWaitForCore = true;
1056 while(m_bWaitForCore)
1057 Application::Yield();
1059 m_pCore->setUpdateListener(0);
1060 m_eRecoveryState = RecoveryDialog::E_RECOVERY_CORE_DONE;
1061 return execute();
1064 case RecoveryDialog::E_RECOVERY_CORE_DONE :
1066 // the core finished it's task.
1067 // let the user decide the next step.
1068 m_aDescrFT.SetText(m_aRecoveryOnlyFinishDescr);
1069 m_aNextBtn.SetText(m_aRecoveryOnlyFinish);
1070 m_aNextBtn.Enable(true);
1071 m_aCancelBtn.Enable(false);
1073 m_bWaitForUser = true;
1074 while(m_bWaitForUser)
1075 Application::Yield();
1077 if (m_bUserDecideNext)
1078 m_eRecoveryState = RecoveryDialog::E_RECOVERY_DONE;
1079 else
1080 m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED;
1081 return execute();
1084 case RecoveryDialog::E_RECOVERY_DONE :
1086 // All documents was reovered.
1087 // User decided to step to the "next" wizard page.
1088 // Do it ... but check first, if there exist some
1089 // failed recovery documents. They must be saved to
1090 // a user selected directrory.
1091 short nRet = DLG_RET_UNKNOWN;
1092 BrokenRecoveryDialog* pBrokenRecoveryDialog = new BrokenRecoveryDialog(this, m_pCore, !m_bWasRecoveryStarted);
1093 OUString sSaveDir = pBrokenRecoveryDialog->getSaveDirURL(); // get the default dir
1094 if (pBrokenRecoveryDialog->isExecutionNeeded())
1096 nRet = pBrokenRecoveryDialog->Execute();
1097 sSaveDir = pBrokenRecoveryDialog->getSaveDirURL();
1099 delete pBrokenRecoveryDialog;
1101 switch(nRet)
1103 // no broken temp files exists
1104 // step to the next wizard page
1105 case DLG_RET_UNKNOWN :
1107 m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1108 return DLG_RET_OK;
1111 // user decided to save the broken temp files
1112 // do and forget it
1113 // step to the next wizard page
1114 case DLG_RET_OK :
1116 m_pCore->saveBrokenTempEntries(sSaveDir);
1117 m_pCore->forgetBrokenTempEntries();
1118 m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1119 return DLG_RET_OK;
1122 // user decided to ignore broken temp files.
1123 // Ask it again ... may be this decision was wrong.
1124 // Results:
1125 // IGNORE => remove broken temp files
1126 // => step to the next wizard page
1127 // CANCEL => step back to the recovery page
1128 case DLG_RET_CANCEL :
1130 // TODO ask user ...
1131 m_pCore->forgetBrokenTempEntries();
1132 m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1133 return DLG_RET_OK;
1137 m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1138 return DLG_RET_OK;
1141 case RecoveryDialog::E_RECOVERY_CANCELED :
1143 // "YES" => break recovery
1144 // But there exist different states, where "cancel" can be called.
1145 // Handle it different.
1146 if (m_bWasRecoveryStarted)
1147 m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED_AFTERWARDS;
1148 else
1149 m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED_BEFORE;
1150 return execute();
1153 case RecoveryDialog::E_RECOVERY_CANCELED_BEFORE :
1154 case RecoveryDialog::E_RECOVERY_CANCELED_AFTERWARDS :
1156 // We have to check if there exists some temp. files.
1157 // They should be saved to a user defined location.
1158 // If no temp files exists or user decided to ignore it ...
1159 // we have to remove all recovery/session data anyway!
1160 short nRet = DLG_RET_UNKNOWN;
1161 BrokenRecoveryDialog* pBrokenRecoveryDialog = new BrokenRecoveryDialog(this, m_pCore, !m_bWasRecoveryStarted);
1162 OUString sSaveDir = pBrokenRecoveryDialog->getSaveDirURL(); // get the default save location
1164 // dialog itself checks if there is a need to copy files for this mode.
1165 // It uses the information m_bWasRecoveryStarted doing so.
1166 if (pBrokenRecoveryDialog->isExecutionNeeded())
1168 nRet = pBrokenRecoveryDialog->Execute();
1169 sSaveDir = pBrokenRecoveryDialog->getSaveDirURL();
1171 delete pBrokenRecoveryDialog;
1173 // Possible states:
1174 // a) nRet == DLG_RET_UNKNOWN
1175 // dialog was not shown ...
1176 // because there exists no temp file for copy.
1177 // => remove all recovery data
1178 // b) nRet == DLG_RET_OK
1179 // dialog was shown ...
1180 // user decided to save temp files
1181 // => save all OR broken temp files (depends from the time, where cancel was called)
1182 // => remove all recovery data
1183 // c) nRet == DLG_RET_CANCEL
1184 // dialog was shown ...
1185 // user decided to ignore temp files
1186 // => remove all recovery data
1187 // => a)/c) are the same ... b) has one additional operation
1189 // b)
1190 if (nRet == DLG_RET_OK)
1192 if (m_bWasRecoveryStarted)
1193 m_pCore->saveBrokenTempEntries(sSaveDir);
1194 else
1195 m_pCore->saveAllTempEntries(sSaveDir);
1198 // a,b,c)
1199 if (m_bWasRecoveryStarted)
1200 m_pCore->forgetBrokenRecoveryEntries();
1201 else
1202 m_pCore->forgetAllRecoveryEntries();
1203 m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1205 // THERE IS NO WAY BACK. see impl_askUserForWizardCancel()!
1206 return DLG_RET_CANCEL;
1209 case RecoveryDialog::E_RECOVERY_HANDLED :
1211 m_bWaitForUser = true;
1212 while(m_bWaitForUser)
1213 Application::Yield();
1215 // TODO: show BrokenRecoveryDialog again, ift he user
1216 // doesn't accepted it last time.
1218 if (m_bUserDecideNext)
1219 return DLG_RET_OK;
1220 else
1221 return DLG_RET_CANCEL;
1225 // should never be reached .-)
1226 OSL_FAIL("Should never be reached!");
1227 return DLG_RET_OK;
1231 void RecoveryDialog::setDefButton()
1233 if ( m_aNextBtn.IsEnabled() )
1234 m_aNextBtn.GrabFocus();
1235 else
1236 m_pDefButton = &m_aNextBtn;
1240 void RecoveryDialog::start()
1245 void RecoveryDialog::updateItems()
1247 sal_uIntPtr c = m_aFileListLB.GetEntryCount();
1248 sal_uIntPtr i = 0;
1249 for ( i=0; i<c; ++i )
1251 SvTreeListEntry* pEntry = m_aFileListLB.GetEntry(i);
1252 if ( !pEntry )
1253 continue;
1255 TURLInfo* pInfo = (TURLInfo*)pEntry->GetUserData();
1256 if ( !pInfo )
1257 continue;
1259 OUString sStatus = impl_getStatusString( *pInfo );
1260 if ( !sStatus.isEmpty() )
1261 m_aFileListLB.SetEntryText( sStatus, pEntry, 1 );
1264 m_aFileListLB.Invalidate();
1265 m_aFileListLB.Update();
1269 void RecoveryDialog::stepNext(TURLInfo* pItem)
1271 sal_uIntPtr c = m_aFileListLB.GetEntryCount();
1272 sal_uIntPtr i = 0;
1273 for (i=0; i<c; ++i)
1275 SvTreeListEntry* pEntry = m_aFileListLB.GetEntry(i);
1276 if (!pEntry)
1277 continue;
1279 TURLInfo* pInfo = (TURLInfo*)pEntry->GetUserData();
1280 if (pInfo->ID != pItem->ID)
1281 continue;
1283 m_aFileListLB.SetCursor(pEntry, true);
1284 m_aFileListLB.MakeVisible(pEntry);
1285 m_aFileListLB.Invalidate();
1286 m_aFileListLB.Update();
1287 break;
1292 void RecoveryDialog::end()
1294 if ( m_pDefButton )
1296 m_pDefButton->GrabFocus();
1297 m_pDefButton = NULL;
1299 m_bWaitForCore = false;
1303 IMPL_LINK_NOARG(RecoveryDialog, NextButtonHdl)
1305 m_bUserDecideNext = true;
1306 m_bWaitForUser = false;
1307 return 0;
1311 IMPL_LINK_NOARG(RecoveryDialog, CancelButtonHdl)
1313 if (m_eRecoveryState == RecoveryDialog::E_RECOVERY_PREPARED)
1315 if (impl_askUserForWizardCancel(this, RID_SVXQB_EXIT_RECOVERY) == DLG_RET_CANCEL)
1316 return 0;
1318 m_bUserDecideNext = false;
1319 m_bWaitForUser = false;
1320 return 0;
1324 OUString RecoveryDialog::impl_getStatusString( const TURLInfo& rInfo ) const
1326 OUString sStatus;
1327 switch ( rInfo.RecoveryState )
1329 case E_SUCCESSFULLY_RECOVERED :
1330 sStatus = m_aFileListLB.m_aSuccessRecovStr;
1331 break;
1332 case E_ORIGINAL_DOCUMENT_RECOVERED :
1333 sStatus = m_aFileListLB.m_aOrigDocRecovStr;
1334 break;
1335 case E_RECOVERY_FAILED :
1336 sStatus = m_aFileListLB.m_aRecovFailedStr;
1337 break;
1338 case E_RECOVERY_IS_IN_PROGRESS :
1339 sStatus = m_aFileListLB.m_aRecovInProgrStr;
1340 break;
1341 case E_NOT_RECOVERED_YET :
1342 sStatus = m_aFileListLB.m_aNotRecovYetStr;
1343 break;
1344 default:
1345 break;
1347 return sStatus;
1351 BrokenRecoveryDialog::BrokenRecoveryDialog(Window* pParent ,
1352 RecoveryCore* pCore ,
1353 bool bBeforeRecovery)
1354 : ModalDialog ( pParent, SVX_RES( RID_SVX_MDLG_DOCRECOVERY_BROKEN ) )
1355 , m_aDescrFT ( this , SVX_RES( FT_BROKEN_DESCR ) )
1356 , m_aFileListFT ( this , SVX_RES( FT_BROKEN_FILELIST ) )
1357 , m_aFileListLB ( this , SVX_RES( LB_BROKEN_FILELIST ) )
1358 , m_aSaveDirFT ( this , SVX_RES( FT_BROKEN_SAVEDIR ) )
1359 , m_aSaveDirED ( this , SVX_RES( ED_BROKEN_SAVEDIR ) )
1360 , m_aSaveDirBtn ( this , SVX_RES( BTN_BROKEN_SAVEDIR ) )
1361 , m_aBottomFL ( this , SVX_RES( FL_BROKEN_BOTTOM ) )
1362 , m_aOkBtn ( this , SVX_RES( BTN_BROKEN_OK ) )
1363 , m_aCancelBtn ( this , SVX_RES( BTN_BROKEN_CANCEL ) )
1364 , m_pCore ( pCore )
1365 , m_bBeforeRecovery (bBeforeRecovery)
1366 , m_bExecutionNeeded(false)
1368 FreeResource();
1370 m_aSaveDirBtn.SetClickHdl( LINK( this, BrokenRecoveryDialog, SaveButtonHdl ) );
1371 m_aOkBtn.SetClickHdl( LINK( this, BrokenRecoveryDialog, OkButtonHdl ) );
1372 m_aCancelBtn.SetClickHdl( LINK( this, BrokenRecoveryDialog, CancelButtonHdl ) );
1374 m_sSavePath = SvtPathOptions().GetWorkPath();
1375 INetURLObject aObj( m_sSavePath );
1376 OUString sPath;
1377 ::utl::LocalFileHelper::ConvertURLToSystemPath( aObj.GetMainURL( INetURLObject::NO_DECODE ), sPath );
1378 m_aSaveDirED.SetText( sPath );
1380 impl_refresh();
1384 BrokenRecoveryDialog::~BrokenRecoveryDialog()
1389 void BrokenRecoveryDialog::impl_refresh()
1391 m_bExecutionNeeded = false;
1392 TURLList* pURLList = m_pCore->getURLListAccess();
1393 TURLList::const_iterator pIt;
1394 for ( pIt = pURLList->begin();
1395 pIt != pURLList->end() ;
1396 ++pIt )
1398 const TURLInfo& rInfo = *pIt;
1400 if (m_bBeforeRecovery)
1402 // "Cancel" before recovery ->
1403 // search for any temp files!
1404 if (rInfo.TempURL.isEmpty())
1405 continue;
1407 else
1409 // "Cancel" after recovery ->
1410 // search for broken temp files
1411 if (!RecoveryCore::isBrokenTempEntry(rInfo))
1412 continue;
1415 m_bExecutionNeeded = true;
1417 sal_uInt16 nPos = m_aFileListLB.InsertEntry(rInfo.DisplayName, rInfo.StandardImage );
1418 m_aFileListLB.SetEntryData( nPos, (void*)&rInfo );
1420 m_sSavePath = "";
1421 m_aOkBtn.GrabFocus();
1425 bool BrokenRecoveryDialog::isExecutionNeeded()
1427 return m_bExecutionNeeded;
1431 OUString BrokenRecoveryDialog::getSaveDirURL()
1433 return m_sSavePath;
1437 IMPL_LINK_NOARG(BrokenRecoveryDialog, OkButtonHdl)
1439 OUString sPhysicalPath = comphelper::string::strip(m_aSaveDirED.GetText(), ' ');
1440 OUString sURL;
1441 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sPhysicalPath, sURL );
1442 m_sSavePath = sURL;
1443 while (m_sSavePath.isEmpty())
1444 impl_askForSavePath();
1446 EndDialog(DLG_RET_OK);
1447 return 0;
1451 IMPL_LINK_NOARG(BrokenRecoveryDialog, CancelButtonHdl)
1453 EndDialog(DLG_RET_CANCEL);
1454 return 0;
1458 IMPL_LINK_NOARG(BrokenRecoveryDialog, SaveButtonHdl)
1460 impl_askForSavePath();
1461 return 0;
1465 void BrokenRecoveryDialog::impl_askForSavePath()
1467 css::uno::Reference< css::ui::dialogs::XFolderPicker2 > xFolderPicker =
1468 css::ui::dialogs::FolderPicker::create( m_pCore->getComponentContext() );
1470 INetURLObject aURL(m_sSavePath, INET_PROT_FILE);
1471 xFolderPicker->setDisplayDirectory(aURL.GetMainURL(INetURLObject::NO_DECODE));
1472 short nRet = xFolderPicker->execute();
1473 if (nRet == css::ui::dialogs::ExecutableDialogResults::OK)
1475 m_sSavePath = xFolderPicker->getDirectory();
1476 OUString sPath;
1477 ::utl::LocalFileHelper::ConvertURLToSystemPath( m_sSavePath, sPath );
1478 m_aSaveDirED.SetText( sPath );
1482 } // namespace DocRecovery
1483 } // namespace svx
1485 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */