Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <config_folders.h>
21 :
22 : #include <sal/macros.h>
23 :
24 : #include <svx/dialmgr.hxx>
25 : #include <svx/dialogs.hrc>
26 : #include "docrecovery.hxx"
27 : #include "docrecovery.hrc"
28 :
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>
40 :
41 : #include <toolkit/helper/vclunohelper.hxx>
42 :
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>
61 :
62 : namespace svx{
63 : namespace DocRecovery{
64 :
65 : using namespace ::rtl;
66 : using namespace ::osl;
67 :
68 :
69 0 : TabDialog4Recovery::TabDialog4Recovery(Window* pParent)
70 0 : : TabDialog (pParent, SVX_RES( RID_SVX_TABDLG_DOCRECOVERY ))
71 0 : , m_pActualPage(m_lTabPages.begin() )
72 : {
73 0 : }
74 :
75 :
76 0 : TabDialog4Recovery::~TabDialog4Recovery()
77 : {
78 0 : m_lTabPages.clear();
79 0 : }
80 :
81 :
82 0 : void TabDialog4Recovery::addTabPage(IExtendedTabPage* pPage)
83 : {
84 0 : if (pPage)
85 0 : m_lTabPages.push_back(pPage);
86 0 : }
87 :
88 :
89 0 : short TabDialog4Recovery::Execute()
90 : {
91 0 : ::SolarMutexGuard aLock;
92 :
93 0 : Show();
94 0 : m_pActualPage = m_lTabPages.begin();
95 : while(true)
96 : {
97 0 : IExtendedTabPage* pPage = *m_pActualPage;
98 0 : SetViewWindow(pPage);
99 0 : pPage->Show();
100 0 : pPage->setDefButton();
101 0 : short nRet = pPage->execute();
102 0 : pPage->Hide();
103 :
104 0 : switch(nRet)
105 : {
106 : case DLG_RET_OK :
107 : {
108 0 : ++m_pActualPage;
109 0 : if (m_pActualPage == m_lTabPages.end())
110 0 : return nRet;
111 : }
112 0 : break;
113 :
114 : case DLG_RET_BACK :
115 : {
116 0 : if (m_pActualPage != m_lTabPages.begin())
117 0 : --m_pActualPage;
118 : }
119 0 : break;
120 :
121 : case DLG_RET_UNKNOWN :
122 : case DLG_RET_CANCEL :
123 : case DLG_RET_OK_AUTOLUNCH :
124 0 : return nRet;
125 : }
126 0 : }
127 : }
128 :
129 :
130 0 : RecoveryCore::RecoveryCore(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
131 : bool bUsedForSaving)
132 : : m_xContext ( rxContext )
133 : , m_pListener ( 0 )
134 0 : , m_bListenForSaving(bUsedForSaving)
135 : {
136 0 : impl_startListening();
137 0 : }
138 :
139 :
140 0 : RecoveryCore::~RecoveryCore()
141 : {
142 0 : impl_stopListening();
143 0 : }
144 :
145 :
146 0 : css::uno::Reference< css::uno::XComponentContext > RecoveryCore::getComponentContext()
147 : {
148 0 : return m_xContext;
149 : }
150 :
151 :
152 0 : TURLList* RecoveryCore::getURLListAccess()
153 : {
154 0 : return &m_lURLs;
155 : }
156 :
157 :
158 0 : bool RecoveryCore::isBrokenTempEntry(const TURLInfo& rInfo)
159 : {
160 0 : if (rInfo.TempURL.isEmpty())
161 0 : return false;
162 :
163 : // Note: If the original files was recovery ... but a temp file
164 : // exists ... an error inside the temp file exists!
165 0 : if (
166 0 : !(rInfo.RecoveryState == E_RECOVERY_FAILED ) &&
167 0 : !(rInfo.RecoveryState == E_ORIGINAL_DOCUMENT_RECOVERED)
168 : )
169 0 : return false;
170 :
171 0 : return true;
172 : }
173 :
174 :
175 0 : void RecoveryCore::saveBrokenTempEntries(const OUString& rPath)
176 : {
177 0 : if (rPath.isEmpty())
178 0 : return;
179 :
180 0 : if (!m_xRealCore.is())
181 0 : return;
182 :
183 : // prepare all needed parameters for the following dispatch() request.
184 0 : css::util::URL aCopyURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_BACKUP);
185 0 : css::uno::Sequence< css::beans::PropertyValue > lCopyArgs(3);
186 0 : lCopyArgs[0].Name = PROP_DISPATCHASYNCHRON;
187 0 : lCopyArgs[0].Value <<= sal_False;
188 0 : lCopyArgs[1].Name = PROP_SAVEPATH;
189 0 : lCopyArgs[1].Value <<= rPath;
190 0 : lCopyArgs[2].Name = PROP_ENTRYID;
191 : // lCopyArgs[2].Value will be changed during next loop ...
192 :
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 0 : TURLList lURLs = m_lURLs;
198 0 : TURLList::const_iterator pIt;
199 0 : for ( pIt = lURLs.begin();
200 0 : pIt != lURLs.end() ;
201 : ++pIt )
202 : {
203 0 : const TURLInfo& rInfo = *pIt;
204 0 : if (!RecoveryCore::isBrokenTempEntry(rInfo))
205 0 : continue;
206 :
207 0 : lCopyArgs[2].Value <<= rInfo.ID;
208 0 : m_xRealCore->dispatch(aCopyURL, lCopyArgs);
209 0 : }
210 : }
211 :
212 :
213 0 : void RecoveryCore::saveAllTempEntries(const OUString& rPath)
214 : {
215 0 : if (rPath.isEmpty())
216 0 : return;
217 :
218 0 : if (!m_xRealCore.is())
219 0 : return;
220 :
221 : // prepare all needed parameters for the following dispatch() request.
222 0 : css::util::URL aCopyURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_BACKUP);
223 0 : css::uno::Sequence< css::beans::PropertyValue > lCopyArgs(3);
224 0 : lCopyArgs[0].Name = PROP_DISPATCHASYNCHRON;
225 0 : lCopyArgs[0].Value <<= sal_False;
226 0 : lCopyArgs[1].Name = PROP_SAVEPATH;
227 0 : lCopyArgs[1].Value <<= rPath;
228 0 : lCopyArgs[2].Name = PROP_ENTRYID;
229 : // lCopyArgs[2].Value will be changed during next loop ...
230 :
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 0 : TURLList lURLs = m_lURLs;
236 0 : TURLList::const_iterator pIt;
237 0 : for ( pIt = lURLs.begin();
238 0 : pIt != lURLs.end() ;
239 : ++pIt )
240 : {
241 0 : const TURLInfo& rInfo = *pIt;
242 0 : if (rInfo.TempURL.isEmpty())
243 0 : continue;
244 :
245 0 : lCopyArgs[2].Value <<= rInfo.ID;
246 0 : m_xRealCore->dispatch(aCopyURL, lCopyArgs);
247 0 : }
248 : }
249 :
250 :
251 0 : void RecoveryCore::forgetBrokenTempEntries()
252 : {
253 0 : if (!m_xRealCore.is())
254 0 : return;
255 :
256 0 : css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
257 0 : css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
258 0 : lRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
259 0 : lRemoveArgs[0].Value <<= sal_False;
260 0 : lRemoveArgs[1].Name = PROP_ENTRYID;
261 : // lRemoveArgs[1].Value will be changed during next loop ...
262 :
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 0 : TURLList lURLs = m_lURLs;
268 0 : TURLList::const_iterator pIt;
269 0 : for ( pIt = lURLs.begin();
270 0 : pIt != lURLs.end() ;
271 : ++pIt )
272 : {
273 0 : const TURLInfo& rInfo = *pIt;
274 0 : if (!RecoveryCore::isBrokenTempEntry(rInfo))
275 0 : continue;
276 :
277 0 : lRemoveArgs[1].Value <<= rInfo.ID;
278 0 : m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
279 0 : }
280 : }
281 :
282 :
283 0 : void RecoveryCore::forgetAllRecoveryEntries()
284 : {
285 0 : if (!m_xRealCore.is())
286 0 : return;
287 :
288 0 : css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
289 0 : css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
290 0 : lRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
291 0 : lRemoveArgs[0].Value <<= sal_False;
292 0 : lRemoveArgs[1].Name = PROP_ENTRYID;
293 : // lRemoveArgs[1].Value will be changed during next loop ...
294 :
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 0 : TURLList lURLs = m_lURLs;
300 0 : TURLList::const_iterator pIt;
301 0 : for ( pIt = lURLs.begin();
302 0 : pIt != lURLs.end() ;
303 : ++pIt )
304 : {
305 0 : const TURLInfo& rInfo = *pIt;
306 0 : lRemoveArgs[1].Value <<= rInfo.ID;
307 0 : m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
308 0 : }
309 : }
310 :
311 :
312 0 : void RecoveryCore::forgetBrokenRecoveryEntries()
313 : {
314 0 : if (!m_xRealCore.is())
315 0 : return;
316 :
317 0 : css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
318 0 : css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
319 0 : lRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
320 0 : lRemoveArgs[0].Value <<= sal_False;
321 0 : lRemoveArgs[1].Name = PROP_ENTRYID;
322 : // lRemoveArgs[1].Value will be changed during next loop ...
323 :
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 0 : TURLList lURLs = m_lURLs;
329 0 : TURLList::const_iterator pIt;
330 0 : for ( pIt = lURLs.begin();
331 0 : pIt != lURLs.end() ;
332 : ++pIt )
333 : {
334 0 : const TURLInfo& rInfo = *pIt;
335 0 : if (!RecoveryCore::isBrokenTempEntry(rInfo))
336 0 : continue;
337 :
338 0 : lRemoveArgs[1].Value <<= rInfo.ID;
339 0 : m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
340 0 : }
341 : }
342 :
343 :
344 0 : void RecoveryCore::setProgressHandler(const css::uno::Reference< css::task::XStatusIndicator >& xProgress)
345 : {
346 0 : m_xProgress = xProgress;
347 0 : }
348 :
349 :
350 0 : void RecoveryCore::setUpdateListener(IRecoveryUpdateListener* pListener)
351 : {
352 0 : m_pListener = pListener;
353 0 : }
354 :
355 :
356 0 : void RecoveryCore::doEmergencySavePrepare()
357 : {
358 0 : if (!m_xRealCore.is())
359 0 : return;
360 :
361 0 : css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_PREPARE_EMERGENCY_SAVE);
362 :
363 0 : css::uno::Sequence< css::beans::PropertyValue > lArgs(1);
364 0 : lArgs[0].Name = PROP_DISPATCHASYNCHRON;
365 0 : lArgs[0].Value <<= sal_False;
366 :
367 0 : m_xRealCore->dispatch(aURL, lArgs);
368 : }
369 :
370 :
371 0 : void RecoveryCore::doEmergencySave()
372 : {
373 0 : if (!m_xRealCore.is())
374 0 : return;
375 :
376 0 : css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_EMERGENCY_SAVE);
377 :
378 0 : css::uno::Sequence< css::beans::PropertyValue > lArgs(2);
379 0 : lArgs[0].Name = PROP_STATUSINDICATOR;
380 0 : lArgs[0].Value <<= m_xProgress;
381 0 : lArgs[1].Name = PROP_DISPATCHASYNCHRON;
382 0 : lArgs[1].Value <<= sal_True;
383 :
384 0 : m_xRealCore->dispatch(aURL, lArgs);
385 : }
386 :
387 :
388 0 : void RecoveryCore::doRecovery()
389 : {
390 0 : if (!m_xRealCore.is())
391 0 : return;
392 :
393 0 : css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_RECOVERY);
394 :
395 0 : css::uno::Sequence< css::beans::PropertyValue > lArgs(2);
396 0 : lArgs[0].Name = PROP_STATUSINDICATOR;
397 0 : lArgs[0].Value <<= m_xProgress;
398 0 : lArgs[1].Name = PROP_DISPATCHASYNCHRON;
399 0 : lArgs[1].Value <<= sal_True;
400 :
401 0 : m_xRealCore->dispatch(aURL, lArgs);
402 : }
403 :
404 :
405 0 : ERecoveryState RecoveryCore::mapDocState2RecoverState(sal_Int32 eDocState)
406 : {
407 : // ???
408 0 : ERecoveryState eRecState = E_NOT_RECOVERED_YET;
409 :
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!
413 :
414 : DAMAGED -> INCOMPLETE -> HANDLED
415 : */
416 :
417 : // running ...
418 0 : if (
419 0 : ((eDocState & E_TRY_LOAD_BACKUP ) == E_TRY_LOAD_BACKUP ) ||
420 0 : ((eDocState & E_TRY_LOAD_ORIGINAL) == E_TRY_LOAD_ORIGINAL)
421 : )
422 0 : eRecState = E_RECOVERY_IS_IN_PROGRESS;
423 : // red
424 0 : else if ((eDocState & E_DAMAGED) == E_DAMAGED)
425 0 : eRecState = E_RECOVERY_FAILED;
426 : // yellow
427 0 : else if ((eDocState & E_INCOMPLETE) == E_INCOMPLETE)
428 0 : eRecState = E_ORIGINAL_DOCUMENT_RECOVERED;
429 : // green
430 0 : else if ((eDocState & E_SUCCEDED) == E_SUCCEDED)
431 0 : eRecState = E_SUCCESSFULLY_RECOVERED;
432 :
433 0 : return eRecState;
434 : }
435 :
436 :
437 0 : void SAL_CALL RecoveryCore::statusChanged(const css::frame::FeatureStateEvent& aEvent)
438 : throw(css::uno::RuntimeException, std::exception)
439 : {
440 : // a) special notification about start/stop async dispatch!
441 : // FeatureDescriptor = "start" || "stop"
442 0 : if (aEvent.FeatureDescriptor.equals(RECOVERY_OPERATIONSTATE_START))
443 : {
444 0 : if (m_pListener)
445 0 : m_pListener->start();
446 0 : return;
447 : }
448 :
449 0 : if (aEvent.FeatureDescriptor.equals(RECOVERY_OPERATIONSTATE_STOP))
450 : {
451 0 : if (m_pListener)
452 0 : m_pListener->end();
453 0 : return;
454 : }
455 :
456 : // b) normal notification about changed items
457 : // FeatureDescriptor = "Update"
458 : // State = Lits of information [seq< NamedValue >]
459 0 : if (! aEvent.FeatureDescriptor.equals(RECOVERY_OPERATIONSTATE_UPDATE))
460 0 : return;
461 :
462 0 : ::comphelper::SequenceAsHashMap lInfo(aEvent.State);
463 0 : TURLInfo aNew;
464 :
465 0 : aNew.ID = lInfo.getUnpackedValueOrDefault(STATEPROP_ID , (sal_Int32)0 );
466 0 : aNew.DocState = lInfo.getUnpackedValueOrDefault(STATEPROP_STATE , (sal_Int32)0 );
467 0 : aNew.OrgURL = lInfo.getUnpackedValueOrDefault(STATEPROP_ORGURL , OUString());
468 0 : aNew.TempURL = lInfo.getUnpackedValueOrDefault(STATEPROP_TEMPURL , OUString());
469 0 : aNew.FactoryURL = lInfo.getUnpackedValueOrDefault(STATEPROP_FACTORYURL , OUString());
470 0 : aNew.TemplateURL = lInfo.getUnpackedValueOrDefault(STATEPROP_TEMPLATEURL, OUString());
471 0 : aNew.DisplayName = lInfo.getUnpackedValueOrDefault(STATEPROP_TITLE , OUString());
472 0 : aNew.Module = lInfo.getUnpackedValueOrDefault(STATEPROP_MODULE , OUString());
473 :
474 : // search for already existing items and update her nState value ...
475 0 : TURLList::iterator pIt;
476 0 : for ( pIt = m_lURLs.begin();
477 0 : pIt != m_lURLs.end() ;
478 : ++pIt )
479 : {
480 0 : TURLInfo& aOld = *pIt;
481 0 : if (aOld.ID == aNew.ID)
482 : {
483 : // change existing
484 0 : aOld.DocState = aNew.DocState;
485 0 : aOld.RecoveryState = RecoveryCore::mapDocState2RecoverState(aOld.DocState);
486 0 : if (m_pListener)
487 : {
488 0 : m_pListener->updateItems();
489 0 : m_pListener->stepNext(&aOld);
490 : }
491 0 : return;
492 : }
493 : }
494 :
495 : // append as new one
496 : // TODO think about mmatching Module name to a corresponding icon
497 0 : OUString sURL = aNew.OrgURL;
498 0 : if (sURL.isEmpty())
499 0 : sURL = aNew.FactoryURL;
500 0 : if (sURL.isEmpty())
501 0 : sURL = aNew.TempURL;
502 0 : if (sURL.isEmpty())
503 0 : sURL = aNew.TemplateURL;
504 0 : INetURLObject aURL(sURL);
505 0 : aNew.StandardImage = SvFileInformationManager::GetFileImage(aURL, false);
506 :
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 0 : aNew.RecoveryState = E_NOT_RECOVERED_YET;
512 :
513 : // patch DisplayName! Because the document title contain more then the file name ...
514 0 : sal_Int32 i = aNew.DisplayName.indexOf(" - ");
515 0 : if (i > 0)
516 0 : aNew.DisplayName = aNew.DisplayName.copy(0, i);
517 :
518 0 : m_lURLs.push_back(aNew);
519 :
520 0 : if (m_pListener)
521 0 : m_pListener->updateItems();
522 : }
523 :
524 :
525 0 : void SAL_CALL RecoveryCore::disposing(const css::lang::EventObject& /*aEvent*/)
526 : throw(css::uno::RuntimeException, std::exception)
527 : {
528 0 : m_xRealCore.clear();
529 0 : }
530 :
531 :
532 0 : void RecoveryCore::impl_startListening()
533 : {
534 : // listening already initialized ?
535 0 : if (m_xRealCore.is())
536 0 : return;
537 0 : m_xRealCore = css::frame::theAutoRecovery::get(m_xContext);
538 :
539 0 : css::util::URL aURL;
540 0 : if (m_bListenForSaving)
541 0 : aURL.Complete = RECOVERY_CMD_DO_EMERGENCY_SAVE;
542 : else
543 0 : aURL.Complete = RECOVERY_CMD_DO_RECOVERY;
544 0 : css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
545 0 : xParser->parseStrict(aURL);
546 :
547 : /* Note: addStatusListener() call us synchronous back ... so we
548 : will get the complete list of currently open documents! */
549 0 : m_xRealCore->addStatusListener(static_cast< css::frame::XStatusListener* >(this), aURL);
550 : }
551 :
552 :
553 0 : void RecoveryCore::impl_stopListening()
554 : {
555 : // Ignore it, if this instance doesn't listen currently
556 0 : if (!m_xRealCore.is())
557 0 : return;
558 :
559 0 : css::util::URL aURL;
560 0 : if (m_bListenForSaving)
561 0 : aURL.Complete = RECOVERY_CMD_DO_EMERGENCY_SAVE;
562 : else
563 0 : aURL.Complete = RECOVERY_CMD_DO_RECOVERY;
564 0 : css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
565 0 : xParser->parseStrict(aURL);
566 :
567 0 : m_xRealCore->removeStatusListener(static_cast< css::frame::XStatusListener* >(this), aURL);
568 0 : m_xRealCore.clear();
569 : }
570 :
571 :
572 0 : css::util::URL RecoveryCore::impl_getParsedURL(const OUString& sURL)
573 : {
574 0 : css::util::URL aURL;
575 0 : aURL.Complete = sURL;
576 :
577 0 : css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
578 0 : xParser->parseStrict(aURL);
579 :
580 0 : return aURL;
581 : }
582 :
583 :
584 0 : PluginProgressWindow::PluginProgressWindow( Window* pParent ,
585 : const css::uno::Reference< css::lang::XComponent >& xProgress)
586 : : Window (pParent )
587 0 : , m_xProgress(xProgress)
588 : {
589 0 : Show();
590 0 : Size aParentSize = pParent->GetSizePixel();
591 : // align the progressbar to its parent
592 0 : setPosSizePixel( -9, 0, aParentSize.Width() + 15, aParentSize.Height() - 4 );
593 0 : }
594 :
595 :
596 0 : PluginProgressWindow::~PluginProgressWindow()
597 : {
598 0 : if (m_xProgress.is())
599 0 : m_xProgress->dispose();
600 0 : }
601 :
602 :
603 0 : PluginProgress::PluginProgress( Window* pParent,
604 0 : const css::uno::Reference< css::uno::XComponentContext >& xContext )
605 : {
606 0 : m_pPlugProgressWindow = new PluginProgressWindow(pParent, static_cast< css::lang::XComponent* >(this));
607 0 : css::uno::Reference< css::awt::XWindow > xProgressWindow = VCLUnoHelper::GetInterface(m_pPlugProgressWindow);
608 0 : m_xProgressFactory = css::task::StatusIndicatorFactory::createWithWindow(xContext, xProgressWindow, sal_False/*DisableReschedule*/, sal_True/*AllowParentShow*/);
609 0 : m_xProgress = m_xProgressFactory->createStatusIndicator();
610 0 : }
611 :
612 :
613 0 : PluginProgress::~PluginProgress()
614 : {
615 0 : }
616 :
617 :
618 0 : void SAL_CALL PluginProgress::dispose()
619 : throw(css::uno::RuntimeException, std::exception)
620 : {
621 : // m_pPluginProgressWindow was deleted ...
622 : // So the internal pointer of this progress
623 : // weill be dead!
624 0 : m_xProgress.clear();
625 0 : }
626 :
627 :
628 0 : void SAL_CALL PluginProgress::addEventListener(const css::uno::Reference< css::lang::XEventListener >& )
629 : throw(css::uno::RuntimeException, std::exception)
630 : {
631 0 : }
632 :
633 :
634 0 : void SAL_CALL PluginProgress::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& )
635 : throw(css::uno::RuntimeException, std::exception)
636 : {
637 0 : }
638 :
639 :
640 0 : void SAL_CALL PluginProgress::start(const OUString&,
641 : sal_Int32 nRange)
642 : throw(css::uno::RuntimeException, std::exception)
643 : {
644 0 : if (m_xProgress.is())
645 0 : m_xProgress->start(OUString(), nRange);
646 0 : }
647 :
648 :
649 0 : void SAL_CALL PluginProgress::end()
650 : throw(css::uno::RuntimeException, std::exception)
651 : {
652 0 : if (m_xProgress.is())
653 0 : m_xProgress->end();
654 0 : }
655 :
656 :
657 0 : void SAL_CALL PluginProgress::setText(const OUString& sText)
658 : throw(css::uno::RuntimeException, std::exception)
659 : {
660 0 : if (m_xProgress.is())
661 0 : m_xProgress->setText(sText);
662 0 : }
663 :
664 :
665 0 : void SAL_CALL PluginProgress::setValue(sal_Int32 nValue)
666 : throw(css::uno::RuntimeException, std::exception)
667 : {
668 0 : if (m_xProgress.is())
669 0 : m_xProgress->setValue(nValue);
670 0 : }
671 :
672 :
673 0 : void SAL_CALL PluginProgress::reset()
674 : throw(css::uno::RuntimeException, std::exception)
675 : {
676 0 : if (m_xProgress.is())
677 0 : m_xProgress->reset();
678 0 : }
679 :
680 :
681 0 : SaveDialog::SaveDialog(Window* pParent,
682 : RecoveryCore* pCore )
683 0 : : IExtendedTabPage( pParent, SVX_RES( RID_SVXPAGE_DOCRECOVERY_SAVE ) )
684 0 : , m_aTitleFT ( this , SVX_RES ( FT_SAVE_TITLE ) )
685 0 : , m_aTitleWin ( this , SVX_RES ( WIN_SAVE_TITLE ) )
686 0 : , m_aTitleFL ( this , SVX_RES ( FL_SAVE_TITLE ) )
687 0 : , m_aDescrFT ( this , SVX_RES ( FT_SAVE_DESCR ) )
688 0 : , m_aFileListFT ( this , SVX_RES ( FT_SAVE_FILELIST ) )
689 0 : , m_aFileListLB ( this , SVX_RES ( LB_SAVE_FILELIST ) )
690 0 : , m_aBottomFL ( this , SVX_RES ( FL_SAVE_BOTTOM ) )
691 0 : , m_aOkBtn ( this , SVX_RES ( BT_SAVE_OK ) )
692 0 : , m_pCore ( pCore )
693 : {
694 0 : FreeResource();
695 :
696 : // Prepare the office for the following crash save step.
697 : // E.g. hide all open widows so the user cant influence our
698 : // operation .-)
699 0 : m_pCore->doEmergencySavePrepare();
700 :
701 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
702 0 : Wallpaper aBackground(rStyleSettings.GetWindowColor());
703 0 : m_aTitleWin.SetBackground(aBackground);
704 0 : m_aTitleFT.SetBackground (aBackground);
705 :
706 0 : Font aFont(m_aTitleFT.GetFont());
707 0 : aFont.SetWeight(WEIGHT_BOLD);
708 0 : m_aTitleFT.SetFont(aFont);
709 :
710 0 : m_aOkBtn.SetClickHdl( LINK( this, SaveDialog, OKButtonHdl ) );
711 0 : m_aFileListLB.SetControlBackground( rStyleSettings.GetDialogColor() );
712 :
713 : // fill listbox with current open documents
714 0 : m_aFileListLB.Clear();
715 :
716 0 : TURLList* pURLs = m_pCore->getURLListAccess();
717 0 : TURLList::const_iterator pIt;
718 :
719 0 : for ( pIt = pURLs->begin();
720 0 : pIt != pURLs->end() ;
721 : ++pIt )
722 : {
723 0 : const TURLInfo& rInfo = *pIt;
724 0 : m_aFileListLB.InsertEntry( rInfo.DisplayName, rInfo.StandardImage );
725 0 : }
726 0 : }
727 :
728 :
729 0 : SaveDialog::~SaveDialog()
730 : {
731 0 : }
732 :
733 :
734 0 : IMPL_LINK_NOARG(SaveDialog, OKButtonHdl)
735 : {
736 0 : m_nResult = DLG_RET_OK;
737 0 : return 0;
738 : }
739 :
740 :
741 0 : short SaveDialog::execute()
742 : {
743 0 : ::SolarMutexGuard aLock;
744 :
745 : // wait for user input "OK"
746 0 : m_nResult = DLG_RET_UNKNOWN;
747 0 : while(m_nResult == DLG_RET_UNKNOWN)
748 0 : Application::Yield();
749 :
750 : // start crash-save with progress
751 0 : if (m_nResult == DLG_RET_OK)
752 : {
753 0 : SaveProgressDialog* pProgress = new SaveProgressDialog(this, m_pCore);
754 0 : m_nResult = pProgress->Execute();
755 0 : delete pProgress;
756 : }
757 : // if "CANCEL" => return "CANCEL"
758 : // if "OK" => "AUTOLUNCH" always !
759 0 : if (m_nResult == DLG_RET_OK)
760 0 : m_nResult = DLG_RET_OK_AUTOLUNCH;
761 :
762 0 : return m_nResult;
763 : }
764 :
765 :
766 0 : void SaveDialog::setDefButton()
767 : {
768 0 : m_aOkBtn.GrabFocus();
769 0 : }
770 :
771 :
772 0 : SaveProgressDialog::SaveProgressDialog(Window* pParent,
773 : RecoveryCore* pCore )
774 0 : : ModalDialog ( pParent , SVX_RES( RID_SVX_MDLG_DOCRECOVERY_PROGR ) )
775 0 : , m_aHintFT ( this , SVX_RES ( FT_SAVEPROGR_HINT ) )
776 0 : , m_aProgrFT ( this , SVX_RES ( FT_SAVEPROGR_PROGR ) )
777 0 : , m_aProgrParent( this , SVX_RES ( WIN_SAVEPROGR_PROGR ) )
778 0 : , m_pCore ( pCore )
779 : {
780 0 : FreeResource();
781 0 : PluginProgress* pProgress = new PluginProgress( &m_aProgrParent, pCore->getComponentContext() );
782 0 : m_xProgress = css::uno::Reference< css::task::XStatusIndicator >(static_cast< css::task::XStatusIndicator* >(pProgress), css::uno::UNO_QUERY_THROW);
783 0 : }
784 :
785 :
786 0 : SaveProgressDialog::~SaveProgressDialog()
787 : {
788 0 : }
789 :
790 :
791 0 : short SaveProgressDialog::Execute()
792 : {
793 0 : ::SolarMutexGuard aLock;
794 :
795 0 : m_pCore->setProgressHandler(m_xProgress);
796 0 : m_pCore->setUpdateListener(this);
797 0 : m_pCore->doEmergencySave();
798 0 : short nRet = ModalDialog::Execute();
799 0 : m_pCore->setUpdateListener(0);
800 0 : return nRet;
801 : }
802 :
803 :
804 0 : void SaveProgressDialog::updateItems()
805 : {
806 0 : }
807 :
808 :
809 0 : void SaveProgressDialog::stepNext(TURLInfo* )
810 : {
811 : /* TODO
812 :
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 ...
816 : */
817 0 : }
818 :
819 :
820 0 : void SaveProgressDialog::start()
821 : {
822 0 : }
823 :
824 :
825 0 : void SaveProgressDialog::end()
826 : {
827 0 : EndDialog(DLG_RET_OK);
828 0 : }
829 :
830 :
831 0 : RecovDocListEntry::RecovDocListEntry( SvTreeListEntry* pEntry,
832 : sal_uInt16 nFlags,
833 : const OUString& sText )
834 0 : : SvLBoxString( pEntry, nFlags, sText )
835 : {
836 0 : }
837 :
838 :
839 0 : void RecovDocListEntry::Paint(
840 : const Point& aPos, SvTreeListBox& aDevice, const SvViewDataEntry* /*pView*/, const SvTreeListEntry* pEntry)
841 : {
842 0 : const Image* pImg = 0;
843 0 : const OUString* pTxt = 0;
844 0 : RecovDocList* pList = static_cast< RecovDocList* >(&aDevice);
845 :
846 0 : TURLInfo* pInfo = (TURLInfo*)pEntry->GetUserData();
847 0 : switch(pInfo->RecoveryState)
848 : {
849 : case E_SUCCESSFULLY_RECOVERED :
850 : {
851 0 : pImg = &pList->m_aGreenCheckImg;
852 0 : pTxt = &pList->m_aSuccessRecovStr;
853 : }
854 0 : break;
855 :
856 : case E_ORIGINAL_DOCUMENT_RECOVERED : // TODO must be renamed into ORIGINAL DOCUMENT recovered! Because its marked as yellow
857 : {
858 0 : pImg = &pList->m_aYellowCheckImg;
859 0 : pTxt = &pList->m_aOrigDocRecovStr;
860 : }
861 0 : break;
862 :
863 : case E_RECOVERY_FAILED :
864 : {
865 0 : pImg = &pList->m_aRedCrossImg;
866 0 : pTxt = &pList->m_aRecovFailedStr;
867 : }
868 0 : break;
869 :
870 : case E_RECOVERY_IS_IN_PROGRESS :
871 : {
872 0 : pImg = 0;
873 0 : pTxt = &pList->m_aRecovInProgrStr;
874 : }
875 0 : break;
876 :
877 : case E_NOT_RECOVERED_YET :
878 : {
879 0 : pImg = 0;
880 0 : pTxt = &pList->m_aNotRecovYetStr;
881 : }
882 0 : break;
883 : }
884 :
885 0 : if (pImg)
886 0 : aDevice.DrawImage(aPos, *pImg);
887 :
888 0 : if (pTxt)
889 : {
890 0 : Point aPnt(aPos);
891 0 : aPnt.X() += pList->m_aGreenCheckImg.GetSizePixel().Width();
892 0 : aPnt.X() += 10;
893 0 : aDevice.DrawText(aPnt, *pTxt);
894 : }
895 0 : }
896 :
897 0 : 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 0 : , m_aNotRecovYetStr ( ResId(STR_NOTRECOVYET, rResMgr ) )
907 : {
908 0 : }
909 :
910 :
911 0 : RecovDocList::~RecovDocList()
912 : {
913 0 : }
914 :
915 :
916 0 : void RecovDocList::InitEntry(SvTreeListEntry* pEntry,
917 : const OUString& rText,
918 : const Image& rImage1,
919 : const Image& rImage2,
920 : SvLBoxButtonKind eButtonKind)
921 : {
922 0 : SvTabListBox::InitEntry(pEntry, rText, rImage1, rImage2, eButtonKind);
923 : DBG_ASSERT( TabCount() == 2, "*RecovDocList::InitEntry(): structure missmatch" );
924 :
925 0 : SvLBoxString* pCol = (SvLBoxString*)pEntry->GetItem(2);
926 0 : RecovDocListEntry* p = new RecovDocListEntry(pEntry, 0, pCol->GetText());
927 0 : pEntry->ReplaceItem(p, 2);
928 0 : }
929 :
930 :
931 0 : short impl_askUserForWizardCancel(Window* pParent, sal_Int16 nRes)
932 : {
933 0 : QueryBox aQuery(pParent, SVX_RES(nRes));
934 0 : if (aQuery.Execute() == RET_YES)
935 0 : return DLG_RET_OK;
936 : else
937 0 : return DLG_RET_CANCEL;
938 : }
939 :
940 :
941 0 : RecoveryDialog::RecoveryDialog(Window* pParent,
942 : RecoveryCore* pCore )
943 0 : : IExtendedTabPage( pParent , SVX_RES( RID_SVXPAGE_DOCRECOVERY_RECOVER ) )
944 0 : , m_aTitleFT ( this , SVX_RES ( FT_RECOV_TITLE ) )
945 0 : , m_aTitleWin ( this , SVX_RES ( WIN_RECOV_TITLE ) )
946 0 : , m_aTitleFL ( this , SVX_RES ( FL_RECOV_TITLE ) )
947 0 : , m_aDescrFT ( this , SVX_RES ( FT_RECOV_DESCR ) )
948 0 : , m_aProgressFT ( this , SVX_RES ( FT_RECOV_PROGR ) )
949 0 : , m_aProgrParent ( this , SVX_RES ( WIN_RECOV_PROGR ) )
950 0 : , m_aFileListFT ( this , SVX_RES ( FT_RECOV_FILELIST ) )
951 0 : , m_aFileListLBContainer( this , SVX_RES ( LB_RECOV_FILELIST ) )
952 0 : , m_aFileListLB (m_aFileListLBContainer, DIALOG_MGR())
953 0 : , m_aBottomFL ( this , SVX_RES ( FL_RECOV_BOTTOM ) )
954 0 : , m_aNextBtn ( this , SVX_RES ( BTN_RECOV_NEXT ) )
955 0 : , m_aCancelBtn ( this , SVX_RES ( BTN_RECOV_CANCEL ) )
956 0 : , m_aTitleRecoveryInProgress(SVX_RESSTR(STR_RECOVERY_INPROGRESS))
957 0 : , m_aRecoveryOnlyFinish (SVX_RESSTR(STR_RECOVERYONLY_FINISH))
958 0 : , 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 0 : , m_bWasRecoveryStarted (false)
966 : {
967 : static long nTabs[] = { 2, 0, 40*RECOV_CONTROLWIDTH/100 };
968 0 : m_aFileListLB.SetTabs( &nTabs[0] );
969 0 : m_aFileListLB.InsertHeaderEntry(SVX_RESSTR(STR_HEADERBAR));
970 :
971 0 : FreeResource();
972 :
973 0 : PluginProgress* pProgress = new PluginProgress( &m_aProgrParent, pCore->getComponentContext() );
974 0 : m_xProgress = css::uno::Reference< css::task::XStatusIndicator >(static_cast< css::task::XStatusIndicator* >(pProgress), css::uno::UNO_QUERY_THROW);
975 :
976 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
977 0 : Wallpaper aBackground( rStyleSettings.GetWindowColor() );
978 0 : m_aTitleWin.SetBackground(aBackground);
979 0 : m_aTitleFT.SetBackground (aBackground);
980 :
981 0 : Font aFont(m_aTitleFT.GetFont());
982 0 : aFont.SetWeight(WEIGHT_BOLD);
983 0 : m_aTitleFT.SetFont(aFont);
984 :
985 0 : m_aFileListLB.SetBackground( rStyleSettings.GetDialogColor() );
986 :
987 0 : m_aNextBtn.Enable(true);
988 0 : m_aNextBtn.SetClickHdl( LINK( this, RecoveryDialog, NextButtonHdl ) );
989 0 : m_aCancelBtn.SetClickHdl( LINK( this, RecoveryDialog, CancelButtonHdl ) );
990 :
991 : // fill list box first time
992 0 : TURLList* pURLList = m_pCore->getURLListAccess();
993 0 : TURLList::const_iterator pIt;
994 0 : for ( pIt = pURLList->begin();
995 0 : pIt != pURLList->end() ;
996 : ++pIt )
997 : {
998 0 : const TURLInfo& rInfo = *pIt;
999 :
1000 0 : OUString sName( rInfo.DisplayName );
1001 0 : sName += "\t";
1002 0 : sName += impl_getStatusString( rInfo );
1003 0 : SvTreeListEntry* pEntry = m_aFileListLB.InsertEntry(sName, rInfo.StandardImage, rInfo.StandardImage);
1004 0 : pEntry->SetUserData((void*)&rInfo);
1005 0 : }
1006 :
1007 : // mark first item
1008 0 : SvTreeListEntry* pFirst = m_aFileListLB.First();
1009 0 : if (pFirst)
1010 0 : m_aFileListLB.SetCursor(pFirst, true);
1011 0 : }
1012 :
1013 :
1014 0 : RecoveryDialog::~RecoveryDialog()
1015 : {
1016 0 : }
1017 :
1018 :
1019 0 : short RecoveryDialog::execute()
1020 : {
1021 0 : ::SolarMutexGuard aSolarLock;
1022 :
1023 0 : switch(m_eRecoveryState)
1024 : {
1025 : case RecoveryDialog::E_RECOVERY_PREPARED :
1026 : {
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 0 : m_aNextBtn.Enable(true);
1031 0 : m_aCancelBtn.Enable(true);
1032 0 : m_bWaitForUser = true;
1033 0 : while(m_bWaitForUser)
1034 0 : Application::Yield();
1035 0 : if (m_bUserDecideNext)
1036 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_IN_PROGRESS;
1037 : else
1038 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED;
1039 0 : return execute();
1040 : }
1041 :
1042 : case RecoveryDialog::E_RECOVERY_IN_PROGRESS :
1043 : {
1044 : // user decided to start recovery ...
1045 0 : m_bWasRecoveryStarted = true;
1046 : // do it asynchronous (to allow repaints)
1047 : // and wait for this asynchronous operation.
1048 0 : m_aDescrFT.SetText( m_aTitleRecoveryInProgress );
1049 0 : m_aNextBtn.Enable(false);
1050 0 : m_aCancelBtn.Enable(false);
1051 0 : m_pCore->setProgressHandler(m_xProgress);
1052 0 : m_pCore->setUpdateListener(this);
1053 0 : m_pCore->doRecovery();
1054 :
1055 0 : m_bWaitForCore = true;
1056 0 : while(m_bWaitForCore)
1057 0 : Application::Yield();
1058 :
1059 0 : m_pCore->setUpdateListener(0);
1060 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_CORE_DONE;
1061 0 : return execute();
1062 : }
1063 :
1064 : case RecoveryDialog::E_RECOVERY_CORE_DONE :
1065 : {
1066 : // the core finished it's task.
1067 : // let the user decide the next step.
1068 0 : m_aDescrFT.SetText(m_aRecoveryOnlyFinishDescr);
1069 0 : m_aNextBtn.SetText(m_aRecoveryOnlyFinish);
1070 0 : m_aNextBtn.Enable(true);
1071 0 : m_aCancelBtn.Enable(false);
1072 :
1073 0 : m_bWaitForUser = true;
1074 0 : while(m_bWaitForUser)
1075 0 : Application::Yield();
1076 :
1077 0 : if (m_bUserDecideNext)
1078 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_DONE;
1079 : else
1080 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED;
1081 0 : return execute();
1082 : }
1083 :
1084 : case RecoveryDialog::E_RECOVERY_DONE :
1085 : {
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 0 : short nRet = DLG_RET_UNKNOWN;
1092 0 : BrokenRecoveryDialog* pBrokenRecoveryDialog = new BrokenRecoveryDialog(this, m_pCore, !m_bWasRecoveryStarted);
1093 0 : OUString sSaveDir = pBrokenRecoveryDialog->getSaveDirURL(); // get the default dir
1094 0 : if (pBrokenRecoveryDialog->isExecutionNeeded())
1095 : {
1096 0 : nRet = pBrokenRecoveryDialog->Execute();
1097 0 : sSaveDir = pBrokenRecoveryDialog->getSaveDirURL();
1098 : }
1099 0 : delete pBrokenRecoveryDialog;
1100 :
1101 0 : switch(nRet)
1102 : {
1103 : // no broken temp files exists
1104 : // step to the next wizard page
1105 : case DLG_RET_UNKNOWN :
1106 : {
1107 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1108 0 : return DLG_RET_OK;
1109 : }
1110 :
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 :
1115 : {
1116 0 : m_pCore->saveBrokenTempEntries(sSaveDir);
1117 0 : m_pCore->forgetBrokenTempEntries();
1118 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1119 0 : return DLG_RET_OK;
1120 : }
1121 :
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 :
1129 : {
1130 : // TODO ask user ...
1131 0 : m_pCore->forgetBrokenTempEntries();
1132 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1133 0 : return DLG_RET_OK;
1134 : }
1135 : }
1136 :
1137 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1138 0 : return DLG_RET_OK;
1139 : }
1140 :
1141 : case RecoveryDialog::E_RECOVERY_CANCELED :
1142 : {
1143 : // "YES" => break recovery
1144 : // But there exist different states, where "cancel" can be called.
1145 : // Handle it different.
1146 0 : if (m_bWasRecoveryStarted)
1147 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED_AFTERWARDS;
1148 : else
1149 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED_BEFORE;
1150 0 : return execute();
1151 : }
1152 :
1153 : case RecoveryDialog::E_RECOVERY_CANCELED_BEFORE :
1154 : case RecoveryDialog::E_RECOVERY_CANCELED_AFTERWARDS :
1155 : {
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 0 : short nRet = DLG_RET_UNKNOWN;
1161 0 : BrokenRecoveryDialog* pBrokenRecoveryDialog = new BrokenRecoveryDialog(this, m_pCore, !m_bWasRecoveryStarted);
1162 0 : OUString sSaveDir = pBrokenRecoveryDialog->getSaveDirURL(); // get the default save location
1163 :
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 0 : if (pBrokenRecoveryDialog->isExecutionNeeded())
1167 : {
1168 0 : nRet = pBrokenRecoveryDialog->Execute();
1169 0 : sSaveDir = pBrokenRecoveryDialog->getSaveDirURL();
1170 : }
1171 0 : delete pBrokenRecoveryDialog;
1172 :
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
1188 :
1189 : // b)
1190 0 : if (nRet == DLG_RET_OK)
1191 : {
1192 0 : if (m_bWasRecoveryStarted)
1193 0 : m_pCore->saveBrokenTempEntries(sSaveDir);
1194 : else
1195 0 : m_pCore->saveAllTempEntries(sSaveDir);
1196 : }
1197 :
1198 : // a,b,c)
1199 0 : if (m_bWasRecoveryStarted)
1200 0 : m_pCore->forgetBrokenRecoveryEntries();
1201 : else
1202 0 : m_pCore->forgetAllRecoveryEntries();
1203 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1204 :
1205 : // THERE IS NO WAY BACK. see impl_askUserForWizardCancel()!
1206 0 : return DLG_RET_CANCEL;
1207 : }
1208 :
1209 : case RecoveryDialog::E_RECOVERY_HANDLED :
1210 : {
1211 0 : m_bWaitForUser = true;
1212 0 : while(m_bWaitForUser)
1213 0 : Application::Yield();
1214 :
1215 : // TODO: show BrokenRecoveryDialog again, ift he user
1216 : // doesn't accepted it last time.
1217 :
1218 0 : if (m_bUserDecideNext)
1219 0 : return DLG_RET_OK;
1220 : else
1221 0 : return DLG_RET_CANCEL;
1222 : }
1223 : }
1224 :
1225 : // should never be reached .-)
1226 : OSL_FAIL("Should never be reached!");
1227 0 : return DLG_RET_OK;
1228 : }
1229 :
1230 :
1231 0 : void RecoveryDialog::setDefButton()
1232 : {
1233 0 : if ( m_aNextBtn.IsEnabled() )
1234 0 : m_aNextBtn.GrabFocus();
1235 : else
1236 0 : m_pDefButton = &m_aNextBtn;
1237 0 : }
1238 :
1239 :
1240 0 : void RecoveryDialog::start()
1241 : {
1242 0 : }
1243 :
1244 :
1245 0 : void RecoveryDialog::updateItems()
1246 : {
1247 0 : sal_uIntPtr c = m_aFileListLB.GetEntryCount();
1248 0 : sal_uIntPtr i = 0;
1249 0 : for ( i=0; i<c; ++i )
1250 : {
1251 0 : SvTreeListEntry* pEntry = m_aFileListLB.GetEntry(i);
1252 0 : if ( !pEntry )
1253 0 : continue;
1254 :
1255 0 : TURLInfo* pInfo = (TURLInfo*)pEntry->GetUserData();
1256 0 : if ( !pInfo )
1257 0 : continue;
1258 :
1259 0 : OUString sStatus = impl_getStatusString( *pInfo );
1260 0 : if ( !sStatus.isEmpty() )
1261 0 : m_aFileListLB.SetEntryText( sStatus, pEntry, 1 );
1262 0 : }
1263 :
1264 0 : m_aFileListLB.Invalidate();
1265 0 : m_aFileListLB.Update();
1266 0 : }
1267 :
1268 :
1269 0 : void RecoveryDialog::stepNext(TURLInfo* pItem)
1270 : {
1271 0 : sal_uIntPtr c = m_aFileListLB.GetEntryCount();
1272 0 : sal_uIntPtr i = 0;
1273 0 : for (i=0; i<c; ++i)
1274 : {
1275 0 : SvTreeListEntry* pEntry = m_aFileListLB.GetEntry(i);
1276 0 : if (!pEntry)
1277 0 : continue;
1278 :
1279 0 : TURLInfo* pInfo = (TURLInfo*)pEntry->GetUserData();
1280 0 : if (pInfo->ID != pItem->ID)
1281 0 : continue;
1282 :
1283 0 : m_aFileListLB.SetCursor(pEntry, true);
1284 0 : m_aFileListLB.MakeVisible(pEntry);
1285 0 : m_aFileListLB.Invalidate();
1286 0 : m_aFileListLB.Update();
1287 0 : break;
1288 : }
1289 0 : }
1290 :
1291 :
1292 0 : void RecoveryDialog::end()
1293 : {
1294 0 : if ( m_pDefButton )
1295 : {
1296 0 : m_pDefButton->GrabFocus();
1297 0 : m_pDefButton = NULL;
1298 : }
1299 0 : m_bWaitForCore = false;
1300 0 : }
1301 :
1302 :
1303 0 : IMPL_LINK_NOARG(RecoveryDialog, NextButtonHdl)
1304 : {
1305 0 : m_bUserDecideNext = true;
1306 0 : m_bWaitForUser = false;
1307 0 : return 0;
1308 : }
1309 :
1310 :
1311 0 : IMPL_LINK_NOARG(RecoveryDialog, CancelButtonHdl)
1312 : {
1313 0 : if (m_eRecoveryState == RecoveryDialog::E_RECOVERY_PREPARED)
1314 : {
1315 0 : if (impl_askUserForWizardCancel(this, RID_SVXQB_EXIT_RECOVERY) == DLG_RET_CANCEL)
1316 0 : return 0;
1317 : }
1318 0 : m_bUserDecideNext = false;
1319 0 : m_bWaitForUser = false;
1320 0 : return 0;
1321 : }
1322 :
1323 :
1324 0 : OUString RecoveryDialog::impl_getStatusString( const TURLInfo& rInfo ) const
1325 : {
1326 0 : OUString sStatus;
1327 0 : switch ( rInfo.RecoveryState )
1328 : {
1329 : case E_SUCCESSFULLY_RECOVERED :
1330 0 : sStatus = m_aFileListLB.m_aSuccessRecovStr;
1331 0 : break;
1332 : case E_ORIGINAL_DOCUMENT_RECOVERED :
1333 0 : sStatus = m_aFileListLB.m_aOrigDocRecovStr;
1334 0 : break;
1335 : case E_RECOVERY_FAILED :
1336 0 : sStatus = m_aFileListLB.m_aRecovFailedStr;
1337 0 : break;
1338 : case E_RECOVERY_IS_IN_PROGRESS :
1339 0 : sStatus = m_aFileListLB.m_aRecovInProgrStr;
1340 0 : break;
1341 : case E_NOT_RECOVERED_YET :
1342 0 : sStatus = m_aFileListLB.m_aNotRecovYetStr;
1343 0 : break;
1344 : default:
1345 0 : break;
1346 : }
1347 0 : return sStatus;
1348 : }
1349 :
1350 :
1351 0 : BrokenRecoveryDialog::BrokenRecoveryDialog(Window* pParent ,
1352 : RecoveryCore* pCore ,
1353 : bool bBeforeRecovery)
1354 0 : : ModalDialog ( pParent, SVX_RES( RID_SVX_MDLG_DOCRECOVERY_BROKEN ) )
1355 0 : , m_aDescrFT ( this , SVX_RES( FT_BROKEN_DESCR ) )
1356 0 : , m_aFileListFT ( this , SVX_RES( FT_BROKEN_FILELIST ) )
1357 0 : , m_aFileListLB ( this , SVX_RES( LB_BROKEN_FILELIST ) )
1358 0 : , m_aSaveDirFT ( this , SVX_RES( FT_BROKEN_SAVEDIR ) )
1359 0 : , m_aSaveDirED ( this , SVX_RES( ED_BROKEN_SAVEDIR ) )
1360 0 : , m_aSaveDirBtn ( this , SVX_RES( BTN_BROKEN_SAVEDIR ) )
1361 0 : , m_aBottomFL ( this , SVX_RES( FL_BROKEN_BOTTOM ) )
1362 0 : , m_aOkBtn ( this , SVX_RES( BTN_BROKEN_OK ) )
1363 0 : , m_aCancelBtn ( this , SVX_RES( BTN_BROKEN_CANCEL ) )
1364 : , m_pCore ( pCore )
1365 : , m_bBeforeRecovery (bBeforeRecovery)
1366 0 : , m_bExecutionNeeded(sal_False)
1367 : {
1368 0 : FreeResource();
1369 :
1370 0 : m_aSaveDirBtn.SetClickHdl( LINK( this, BrokenRecoveryDialog, SaveButtonHdl ) );
1371 0 : m_aOkBtn.SetClickHdl( LINK( this, BrokenRecoveryDialog, OkButtonHdl ) );
1372 0 : m_aCancelBtn.SetClickHdl( LINK( this, BrokenRecoveryDialog, CancelButtonHdl ) );
1373 :
1374 0 : m_sSavePath = SvtPathOptions().GetWorkPath();
1375 0 : INetURLObject aObj( m_sSavePath );
1376 0 : OUString sPath;
1377 0 : ::utl::LocalFileHelper::ConvertURLToSystemPath( aObj.GetMainURL( INetURLObject::NO_DECODE ), sPath );
1378 0 : m_aSaveDirED.SetText( sPath );
1379 :
1380 0 : impl_refresh();
1381 0 : }
1382 :
1383 :
1384 0 : BrokenRecoveryDialog::~BrokenRecoveryDialog()
1385 : {
1386 0 : }
1387 :
1388 :
1389 0 : void BrokenRecoveryDialog::impl_refresh()
1390 : {
1391 0 : m_bExecutionNeeded = sal_False;
1392 0 : TURLList* pURLList = m_pCore->getURLListAccess();
1393 0 : TURLList::const_iterator pIt;
1394 0 : for ( pIt = pURLList->begin();
1395 0 : pIt != pURLList->end() ;
1396 : ++pIt )
1397 : {
1398 0 : const TURLInfo& rInfo = *pIt;
1399 :
1400 0 : if (m_bBeforeRecovery)
1401 : {
1402 : // "Cancel" before recovery ->
1403 : // search for any temp files!
1404 0 : if (rInfo.TempURL.isEmpty())
1405 0 : continue;
1406 : }
1407 : else
1408 : {
1409 : // "Cancel" after recovery ->
1410 : // search for broken temp files
1411 0 : if (!RecoveryCore::isBrokenTempEntry(rInfo))
1412 0 : continue;
1413 : }
1414 :
1415 0 : m_bExecutionNeeded = sal_True;
1416 :
1417 0 : sal_uInt16 nPos = m_aFileListLB.InsertEntry(rInfo.DisplayName, rInfo.StandardImage );
1418 0 : m_aFileListLB.SetEntryData( nPos, (void*)&rInfo );
1419 : }
1420 0 : m_sSavePath = "";
1421 0 : m_aOkBtn.GrabFocus();
1422 0 : }
1423 :
1424 :
1425 0 : sal_Bool BrokenRecoveryDialog::isExecutionNeeded()
1426 : {
1427 0 : return m_bExecutionNeeded;
1428 : }
1429 :
1430 :
1431 0 : OUString BrokenRecoveryDialog::getSaveDirURL()
1432 : {
1433 0 : return m_sSavePath;
1434 : }
1435 :
1436 :
1437 0 : IMPL_LINK_NOARG(BrokenRecoveryDialog, OkButtonHdl)
1438 : {
1439 0 : OUString sPhysicalPath = comphelper::string::strip(m_aSaveDirED.GetText(), ' ');
1440 0 : OUString sURL;
1441 0 : ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sPhysicalPath, sURL );
1442 0 : m_sSavePath = sURL;
1443 0 : while (m_sSavePath.isEmpty())
1444 0 : impl_askForSavePath();
1445 :
1446 0 : EndDialog(DLG_RET_OK);
1447 0 : return 0;
1448 : }
1449 :
1450 :
1451 0 : IMPL_LINK_NOARG(BrokenRecoveryDialog, CancelButtonHdl)
1452 : {
1453 0 : EndDialog(DLG_RET_CANCEL);
1454 0 : return 0;
1455 : }
1456 :
1457 :
1458 0 : IMPL_LINK_NOARG(BrokenRecoveryDialog, SaveButtonHdl)
1459 : {
1460 0 : impl_askForSavePath();
1461 0 : return 0;
1462 : }
1463 :
1464 :
1465 0 : void BrokenRecoveryDialog::impl_askForSavePath()
1466 : {
1467 : css::uno::Reference< css::ui::dialogs::XFolderPicker2 > xFolderPicker =
1468 0 : css::ui::dialogs::FolderPicker::create( m_pCore->getComponentContext() );
1469 :
1470 0 : INetURLObject aURL(m_sSavePath, INET_PROT_FILE);
1471 0 : xFolderPicker->setDisplayDirectory(aURL.GetMainURL(INetURLObject::NO_DECODE));
1472 0 : short nRet = xFolderPicker->execute();
1473 0 : if (nRet == css::ui::dialogs::ExecutableDialogResults::OK)
1474 : {
1475 0 : m_sSavePath = xFolderPicker->getDirectory();
1476 0 : OUString sPath;
1477 0 : ::utl::LocalFileHelper::ConvertURLToSystemPath( m_sSavePath, sPath );
1478 0 : m_aSaveDirED.SetText( sPath );
1479 0 : }
1480 0 : }
1481 :
1482 : } // namespace DocRecovery
1483 : } // namespace svx
1484 :
1485 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|