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/layout.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 : #include <boost/scoped_ptr.hpp>
62 :
63 : namespace svx{
64 : namespace DocRecovery{
65 :
66 : using namespace ::osl;
67 :
68 0 : RecoveryCore::RecoveryCore(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
69 : bool bUsedForSaving)
70 : : m_xContext ( rxContext )
71 : , m_pListener ( 0 )
72 0 : , m_bListenForSaving(bUsedForSaving)
73 : {
74 0 : impl_startListening();
75 0 : }
76 :
77 :
78 0 : RecoveryCore::~RecoveryCore()
79 : {
80 0 : impl_stopListening();
81 0 : }
82 :
83 :
84 0 : css::uno::Reference< css::uno::XComponentContext > RecoveryCore::getComponentContext()
85 : {
86 0 : return m_xContext;
87 : }
88 :
89 :
90 0 : TURLList& RecoveryCore::getURLListAccess()
91 : {
92 0 : return m_lURLs;
93 : }
94 :
95 :
96 0 : bool RecoveryCore::isBrokenTempEntry(const TURLInfo& rInfo)
97 : {
98 0 : if (rInfo.TempURL.isEmpty())
99 0 : return false;
100 :
101 : // Note: If the original files was recovery ... but a temp file
102 : // exists ... an error inside the temp file exists!
103 0 : if (
104 0 : !(rInfo.RecoveryState == E_RECOVERY_FAILED ) &&
105 0 : !(rInfo.RecoveryState == E_ORIGINAL_DOCUMENT_RECOVERED)
106 : )
107 0 : return false;
108 :
109 0 : return true;
110 : }
111 :
112 :
113 0 : void RecoveryCore::saveBrokenTempEntries(const OUString& rPath)
114 : {
115 0 : if (rPath.isEmpty())
116 0 : return;
117 :
118 0 : if (!m_xRealCore.is())
119 0 : return;
120 :
121 : // prepare all needed parameters for the following dispatch() request.
122 0 : css::util::URL aCopyURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_BACKUP);
123 0 : css::uno::Sequence< css::beans::PropertyValue > lCopyArgs(3);
124 0 : lCopyArgs[0].Name = PROP_DISPATCHASYNCHRON;
125 0 : lCopyArgs[0].Value <<= sal_False;
126 0 : lCopyArgs[1].Name = PROP_SAVEPATH;
127 0 : lCopyArgs[1].Value <<= rPath;
128 0 : lCopyArgs[2].Name = PROP_ENTRYID;
129 : // lCopyArgs[2].Value will be changed during next loop ...
130 :
131 : // work on a copied list only ...
132 : // Reason: We will get notifications from the core for every
133 : // changed or removed element. And that will change our m_lURLs list.
134 : // That's not a good idea, if we use a stl iterator inbetween .-)
135 0 : TURLList lURLs = m_lURLs;
136 0 : TURLList::const_iterator pIt;
137 0 : for ( pIt = lURLs.begin();
138 0 : pIt != lURLs.end() ;
139 : ++pIt )
140 : {
141 0 : const TURLInfo& rInfo = *pIt;
142 0 : if (!RecoveryCore::isBrokenTempEntry(rInfo))
143 0 : continue;
144 :
145 0 : lCopyArgs[2].Value <<= rInfo.ID;
146 0 : m_xRealCore->dispatch(aCopyURL, lCopyArgs);
147 0 : }
148 : }
149 :
150 :
151 0 : void RecoveryCore::saveAllTempEntries(const OUString& rPath)
152 : {
153 0 : if (rPath.isEmpty())
154 0 : return;
155 :
156 0 : if (!m_xRealCore.is())
157 0 : return;
158 :
159 : // prepare all needed parameters for the following dispatch() request.
160 0 : css::util::URL aCopyURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_BACKUP);
161 0 : css::uno::Sequence< css::beans::PropertyValue > lCopyArgs(3);
162 0 : lCopyArgs[0].Name = PROP_DISPATCHASYNCHRON;
163 0 : lCopyArgs[0].Value <<= sal_False;
164 0 : lCopyArgs[1].Name = PROP_SAVEPATH;
165 0 : lCopyArgs[1].Value <<= rPath;
166 0 : lCopyArgs[2].Name = PROP_ENTRYID;
167 : // lCopyArgs[2].Value will be changed during next loop ...
168 :
169 : // work on a copied list only ...
170 : // Reason: We will get notifications from the core for every
171 : // changed or removed element. And that will change our m_lURLs list.
172 : // That's not a good idea, if we use a stl iterator inbetween .-)
173 0 : TURLList lURLs = m_lURLs;
174 0 : TURLList::const_iterator pIt;
175 0 : for ( pIt = lURLs.begin();
176 0 : pIt != lURLs.end() ;
177 : ++pIt )
178 : {
179 0 : const TURLInfo& rInfo = *pIt;
180 0 : if (rInfo.TempURL.isEmpty())
181 0 : continue;
182 :
183 0 : lCopyArgs[2].Value <<= rInfo.ID;
184 0 : m_xRealCore->dispatch(aCopyURL, lCopyArgs);
185 0 : }
186 : }
187 :
188 :
189 0 : void RecoveryCore::forgetBrokenTempEntries()
190 : {
191 0 : if (!m_xRealCore.is())
192 0 : return;
193 :
194 0 : css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
195 0 : css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
196 0 : lRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
197 0 : lRemoveArgs[0].Value <<= sal_False;
198 0 : lRemoveArgs[1].Name = PROP_ENTRYID;
199 : // lRemoveArgs[1].Value will be changed during next loop ...
200 :
201 : // work on a copied list only ...
202 : // Reason: We will get notifications from the core for every
203 : // changed or removed element. And that will change our m_lURLs list.
204 : // That's not a good idea, if we use a stl iterator inbetween .-)
205 0 : TURLList lURLs = m_lURLs;
206 0 : TURLList::const_iterator pIt;
207 0 : for ( pIt = lURLs.begin();
208 0 : pIt != lURLs.end() ;
209 : ++pIt )
210 : {
211 0 : const TURLInfo& rInfo = *pIt;
212 0 : if (!RecoveryCore::isBrokenTempEntry(rInfo))
213 0 : continue;
214 :
215 0 : lRemoveArgs[1].Value <<= rInfo.ID;
216 0 : m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
217 0 : }
218 : }
219 :
220 :
221 0 : void RecoveryCore::forgetAllRecoveryEntries()
222 : {
223 0 : if (!m_xRealCore.is())
224 0 : return;
225 :
226 0 : css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
227 0 : css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
228 0 : lRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
229 0 : lRemoveArgs[0].Value <<= sal_False;
230 0 : lRemoveArgs[1].Name = PROP_ENTRYID;
231 : // lRemoveArgs[1].Value will be changed during next loop ...
232 :
233 : // work on a copied list only ...
234 : // Reason: We will get notifications from the core for every
235 : // changed or removed element. And that will change our m_lURLs list.
236 : // That's not a good idea, if we use a stl iterator inbetween .-)
237 0 : TURLList lURLs = m_lURLs;
238 0 : TURLList::const_iterator pIt;
239 0 : for ( pIt = lURLs.begin();
240 0 : pIt != lURLs.end() ;
241 : ++pIt )
242 : {
243 0 : const TURLInfo& rInfo = *pIt;
244 0 : lRemoveArgs[1].Value <<= rInfo.ID;
245 0 : m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
246 0 : }
247 : }
248 :
249 :
250 0 : void RecoveryCore::forgetBrokenRecoveryEntries()
251 : {
252 0 : if (!m_xRealCore.is())
253 0 : return;
254 :
255 0 : css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
256 0 : css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
257 0 : lRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
258 0 : lRemoveArgs[0].Value <<= sal_False;
259 0 : lRemoveArgs[1].Name = PROP_ENTRYID;
260 : // lRemoveArgs[1].Value will be changed during next loop ...
261 :
262 : // work on a copied list only ...
263 : // Reason: We will get notifications from the core for every
264 : // changed or removed element. And that will change our m_lURLs list.
265 : // That's not a good idea, if we use a stl iterator inbetween .-)
266 0 : TURLList lURLs = m_lURLs;
267 0 : TURLList::const_iterator pIt;
268 0 : for ( pIt = lURLs.begin();
269 0 : pIt != lURLs.end() ;
270 : ++pIt )
271 : {
272 0 : const TURLInfo& rInfo = *pIt;
273 0 : if (!RecoveryCore::isBrokenTempEntry(rInfo))
274 0 : continue;
275 :
276 0 : lRemoveArgs[1].Value <<= rInfo.ID;
277 0 : m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
278 0 : }
279 : }
280 :
281 :
282 0 : void RecoveryCore::setProgressHandler(const css::uno::Reference< css::task::XStatusIndicator >& xProgress)
283 : {
284 0 : m_xProgress = xProgress;
285 0 : }
286 :
287 :
288 0 : void RecoveryCore::setUpdateListener(IRecoveryUpdateListener* pListener)
289 : {
290 0 : m_pListener = pListener;
291 0 : }
292 :
293 :
294 0 : void RecoveryCore::doEmergencySavePrepare()
295 : {
296 0 : if (!m_xRealCore.is())
297 0 : return;
298 :
299 0 : css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_PREPARE_EMERGENCY_SAVE);
300 :
301 0 : css::uno::Sequence< css::beans::PropertyValue > lArgs(1);
302 0 : lArgs[0].Name = PROP_DISPATCHASYNCHRON;
303 0 : lArgs[0].Value <<= sal_False;
304 :
305 0 : m_xRealCore->dispatch(aURL, lArgs);
306 : }
307 :
308 :
309 0 : void RecoveryCore::doEmergencySave()
310 : {
311 0 : if (!m_xRealCore.is())
312 0 : return;
313 :
314 0 : css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_EMERGENCY_SAVE);
315 :
316 0 : css::uno::Sequence< css::beans::PropertyValue > lArgs(2);
317 0 : lArgs[0].Name = PROP_STATUSINDICATOR;
318 0 : lArgs[0].Value <<= m_xProgress;
319 0 : lArgs[1].Name = PROP_DISPATCHASYNCHRON;
320 0 : lArgs[1].Value <<= sal_True;
321 :
322 0 : m_xRealCore->dispatch(aURL, lArgs);
323 : }
324 :
325 :
326 0 : void RecoveryCore::doRecovery()
327 : {
328 0 : if (!m_xRealCore.is())
329 0 : return;
330 :
331 0 : css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_RECOVERY);
332 :
333 0 : css::uno::Sequence< css::beans::PropertyValue > lArgs(2);
334 0 : lArgs[0].Name = PROP_STATUSINDICATOR;
335 0 : lArgs[0].Value <<= m_xProgress;
336 0 : lArgs[1].Name = PROP_DISPATCHASYNCHRON;
337 0 : lArgs[1].Value <<= sal_True;
338 :
339 0 : m_xRealCore->dispatch(aURL, lArgs);
340 : }
341 :
342 :
343 0 : ERecoveryState RecoveryCore::mapDocState2RecoverState(sal_Int32 eDocState)
344 : {
345 : // ???
346 0 : ERecoveryState eRecState = E_NOT_RECOVERED_YET;
347 :
348 : /* Attention:
349 : Some of the following states can occur at the
350 : same time. So we have to check for the "worst case" first!
351 :
352 : DAMAGED -> INCOMPLETE -> HANDLED
353 : */
354 :
355 : // running ...
356 0 : if (
357 0 : ((eDocState & E_TRY_LOAD_BACKUP ) == E_TRY_LOAD_BACKUP ) ||
358 0 : ((eDocState & E_TRY_LOAD_ORIGINAL) == E_TRY_LOAD_ORIGINAL)
359 : )
360 0 : eRecState = E_RECOVERY_IS_IN_PROGRESS;
361 : // red
362 0 : else if ((eDocState & E_DAMAGED) == E_DAMAGED)
363 0 : eRecState = E_RECOVERY_FAILED;
364 : // yellow
365 0 : else if ((eDocState & E_INCOMPLETE) == E_INCOMPLETE)
366 0 : eRecState = E_ORIGINAL_DOCUMENT_RECOVERED;
367 : // green
368 0 : else if ((eDocState & E_SUCCEDED) == E_SUCCEDED)
369 0 : eRecState = E_SUCCESSFULLY_RECOVERED;
370 :
371 0 : return eRecState;
372 : }
373 :
374 :
375 0 : void SAL_CALL RecoveryCore::statusChanged(const css::frame::FeatureStateEvent& aEvent)
376 : throw(css::uno::RuntimeException, std::exception)
377 : {
378 : // a) special notification about start/stop async dispatch!
379 : // FeatureDescriptor = "start" || "stop"
380 0 : if (aEvent.FeatureDescriptor == RECOVERY_OPERATIONSTATE_START)
381 : {
382 0 : if (m_pListener)
383 0 : m_pListener->start();
384 0 : return;
385 : }
386 :
387 0 : if (aEvent.FeatureDescriptor == RECOVERY_OPERATIONSTATE_STOP)
388 : {
389 0 : if (m_pListener)
390 0 : m_pListener->end();
391 0 : return;
392 : }
393 :
394 : // b) normal notification about changed items
395 : // FeatureDescriptor = "Update"
396 : // State = Lits of information [seq< NamedValue >]
397 0 : if (aEvent.FeatureDescriptor != RECOVERY_OPERATIONSTATE_UPDATE)
398 0 : return;
399 :
400 0 : ::comphelper::SequenceAsHashMap lInfo(aEvent.State);
401 0 : TURLInfo aNew;
402 :
403 0 : aNew.ID = lInfo.getUnpackedValueOrDefault(STATEPROP_ID , (sal_Int32)0 );
404 0 : aNew.DocState = lInfo.getUnpackedValueOrDefault(STATEPROP_STATE , (sal_Int32)0 );
405 0 : aNew.OrgURL = lInfo.getUnpackedValueOrDefault(STATEPROP_ORGURL , OUString());
406 0 : aNew.TempURL = lInfo.getUnpackedValueOrDefault(STATEPROP_TEMPURL , OUString());
407 0 : aNew.FactoryURL = lInfo.getUnpackedValueOrDefault(STATEPROP_FACTORYURL , OUString());
408 0 : aNew.TemplateURL = lInfo.getUnpackedValueOrDefault(STATEPROP_TEMPLATEURL, OUString());
409 0 : aNew.DisplayName = lInfo.getUnpackedValueOrDefault(STATEPROP_TITLE , OUString());
410 0 : aNew.Module = lInfo.getUnpackedValueOrDefault(STATEPROP_MODULE , OUString());
411 :
412 0 : if (aNew.OrgURL.isEmpty()) {
413 : // If there is no file URL, the window title is used for the display name.
414 : // Remove any unwanted elements such as " - LibreOffice Writer".
415 0 : sal_Int32 i = aNew.DisplayName.indexOf(" - ");
416 0 : if (i > 0)
417 0 : aNew.DisplayName = aNew.DisplayName.copy(0, i);
418 : } else {
419 : // If there is a file URL, parse out the filename part as the display name.
420 0 : INetURLObject aOrgURL(aNew.OrgURL);
421 0 : aNew.DisplayName = aOrgURL.getName(INetURLObject::LAST_SEGMENT, true,
422 0 : INetURLObject::DECODE_WITH_CHARSET);
423 : }
424 :
425 : // search for already existing items and update her nState value ...
426 0 : TURLList::iterator pIt;
427 0 : for ( pIt = m_lURLs.begin();
428 0 : pIt != m_lURLs.end() ;
429 : ++pIt )
430 : {
431 0 : TURLInfo& aOld = *pIt;
432 0 : if (aOld.ID == aNew.ID)
433 : {
434 : // change existing
435 0 : aOld.DocState = aNew.DocState;
436 0 : aOld.RecoveryState = RecoveryCore::mapDocState2RecoverState(aOld.DocState);
437 0 : if (m_pListener)
438 : {
439 0 : m_pListener->updateItems();
440 0 : m_pListener->stepNext(&aOld);
441 : }
442 0 : return;
443 : }
444 : }
445 :
446 : // append as new one
447 : // TODO think about mmatching Module name to a corresponding icon
448 0 : OUString sURL = aNew.OrgURL;
449 0 : if (sURL.isEmpty())
450 0 : sURL = aNew.FactoryURL;
451 0 : if (sURL.isEmpty())
452 0 : sURL = aNew.TempURL;
453 0 : if (sURL.isEmpty())
454 0 : sURL = aNew.TemplateURL;
455 0 : INetURLObject aURL(sURL);
456 0 : aNew.StandardImage = SvFileInformationManager::GetFileImage(aURL, false);
457 :
458 : /* set the right UI state for this item to NOT_RECOVERED_YET ... because nDocState shows the state of
459 : the last emergency save operation before and is interessting for the used recovery core service only ...
460 : for now! But if there is a further notification for this item (see lines above!) we must
461 : map the doc state to an UI state. */
462 0 : aNew.RecoveryState = E_NOT_RECOVERED_YET;
463 :
464 0 : m_lURLs.push_back(aNew);
465 :
466 0 : if (m_pListener)
467 0 : m_pListener->updateItems();
468 : }
469 :
470 :
471 0 : void SAL_CALL RecoveryCore::disposing(const css::lang::EventObject& /*aEvent*/)
472 : throw(css::uno::RuntimeException, std::exception)
473 : {
474 0 : m_xRealCore.clear();
475 0 : }
476 :
477 :
478 0 : void RecoveryCore::impl_startListening()
479 : {
480 : // listening already initialized ?
481 0 : if (m_xRealCore.is())
482 0 : return;
483 0 : m_xRealCore = css::frame::theAutoRecovery::get(m_xContext);
484 :
485 0 : css::util::URL aURL;
486 0 : if (m_bListenForSaving)
487 0 : aURL.Complete = RECOVERY_CMD_DO_EMERGENCY_SAVE;
488 : else
489 0 : aURL.Complete = RECOVERY_CMD_DO_RECOVERY;
490 0 : css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
491 0 : xParser->parseStrict(aURL);
492 :
493 : /* Note: addStatusListener() call us synchronous back ... so we
494 : will get the complete list of currently open documents! */
495 0 : m_xRealCore->addStatusListener(static_cast< css::frame::XStatusListener* >(this), aURL);
496 : }
497 :
498 :
499 0 : void RecoveryCore::impl_stopListening()
500 : {
501 : // Ignore it, if this instance doesn't listen currently
502 0 : if (!m_xRealCore.is())
503 0 : return;
504 :
505 0 : css::util::URL aURL;
506 0 : if (m_bListenForSaving)
507 0 : aURL.Complete = RECOVERY_CMD_DO_EMERGENCY_SAVE;
508 : else
509 0 : aURL.Complete = RECOVERY_CMD_DO_RECOVERY;
510 0 : css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
511 0 : xParser->parseStrict(aURL);
512 :
513 0 : m_xRealCore->removeStatusListener(static_cast< css::frame::XStatusListener* >(this), aURL);
514 0 : m_xRealCore.clear();
515 : }
516 :
517 :
518 0 : css::util::URL RecoveryCore::impl_getParsedURL(const OUString& sURL)
519 : {
520 0 : css::util::URL aURL;
521 0 : aURL.Complete = sURL;
522 :
523 0 : css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
524 0 : xParser->parseStrict(aURL);
525 :
526 0 : return aURL;
527 : }
528 :
529 0 : PluginProgressWindow::PluginProgressWindow( vcl::Window* pParent ,
530 : const css::uno::Reference< css::lang::XComponent >& xProgress)
531 : : Window (pParent )
532 0 : , m_xProgress(xProgress)
533 : {
534 0 : Show();
535 0 : Size aParentSize = pParent->GetSizePixel();
536 : // align the progressbar to its parent
537 0 : setPosSizePixel( -9, 0, aParentSize.Width() + 15, aParentSize.Height() - 4 );
538 0 : }
539 :
540 0 : PluginProgressWindow::~PluginProgressWindow()
541 : {
542 0 : disposeOnce();
543 0 : }
544 :
545 0 : void PluginProgressWindow::dispose()
546 : {
547 0 : if (m_xProgress.is())
548 0 : m_xProgress->dispose();
549 0 : vcl::Window::dispose();
550 0 : }
551 :
552 :
553 0 : PluginProgress::PluginProgress( vcl::Window* pParent,
554 0 : const css::uno::Reference< css::uno::XComponentContext >& xContext )
555 : {
556 0 : m_pPlugProgressWindow = VclPtr<PluginProgressWindow>::Create(pParent, static_cast< css::lang::XComponent* >(this));
557 0 : css::uno::Reference< css::awt::XWindow > xProgressWindow = VCLUnoHelper::GetInterface(m_pPlugProgressWindow);
558 0 : m_xProgressFactory = css::task::StatusIndicatorFactory::createWithWindow(xContext, xProgressWindow, sal_False/*DisableReschedule*/, sal_True/*AllowParentShow*/);
559 0 : m_xProgress = m_xProgressFactory->createStatusIndicator();
560 0 : }
561 :
562 :
563 0 : PluginProgress::~PluginProgress()
564 : {
565 0 : }
566 :
567 :
568 0 : void SAL_CALL PluginProgress::dispose()
569 : throw(css::uno::RuntimeException, std::exception)
570 : {
571 : // m_pPluginProgressWindow was deleted ...
572 : // So the internal pointer of this progress
573 : // weill be dead!
574 0 : m_xProgress.clear();
575 0 : }
576 :
577 :
578 0 : void SAL_CALL PluginProgress::addEventListener(const css::uno::Reference< css::lang::XEventListener >& )
579 : throw(css::uno::RuntimeException, std::exception)
580 : {
581 0 : }
582 :
583 :
584 0 : void SAL_CALL PluginProgress::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& )
585 : throw(css::uno::RuntimeException, std::exception)
586 : {
587 0 : }
588 :
589 :
590 0 : void SAL_CALL PluginProgress::start(const OUString&,
591 : sal_Int32 nRange)
592 : throw(css::uno::RuntimeException, std::exception)
593 : {
594 0 : if (m_xProgress.is())
595 0 : m_xProgress->start(OUString(), nRange);
596 0 : }
597 :
598 :
599 0 : void SAL_CALL PluginProgress::end()
600 : throw(css::uno::RuntimeException, std::exception)
601 : {
602 0 : if (m_xProgress.is())
603 0 : m_xProgress->end();
604 0 : }
605 :
606 :
607 0 : void SAL_CALL PluginProgress::setText(const OUString& sText)
608 : throw(css::uno::RuntimeException, std::exception)
609 : {
610 0 : if (m_xProgress.is())
611 0 : m_xProgress->setText(sText);
612 0 : }
613 :
614 :
615 0 : void SAL_CALL PluginProgress::setValue(sal_Int32 nValue)
616 : throw(css::uno::RuntimeException, std::exception)
617 : {
618 0 : if (m_xProgress.is())
619 0 : m_xProgress->setValue(nValue);
620 0 : }
621 :
622 :
623 0 : void SAL_CALL PluginProgress::reset()
624 : throw(css::uno::RuntimeException, std::exception)
625 : {
626 0 : if (m_xProgress.is())
627 0 : m_xProgress->reset();
628 0 : }
629 :
630 :
631 0 : SaveDialog::SaveDialog(vcl::Window* pParent, RecoveryCore* pCore)
632 : : Dialog(pParent, "DocRecoverySaveDialog",
633 : "svx/ui/docrecoverysavedialog.ui")
634 0 : , m_pCore(pCore)
635 : {
636 0 : get(m_pTitleFT, "title");
637 0 : get(m_pFileListLB, "filelist");
638 0 : m_pFileListLB->set_height_request(m_pFileListLB->GetTextHeight() * 10);
639 0 : m_pFileListLB->set_width_request(m_pFileListLB->approximate_char_width() * 72);
640 0 : get(m_pOkBtn, "ok");
641 :
642 : // Prepare the office for the following crash save step.
643 : // E.g. hide all open windows so the user can't influence our
644 : // operation .-)
645 0 : m_pCore->doEmergencySavePrepare();
646 :
647 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
648 0 : m_pTitleFT->SetBackground(rStyleSettings.GetWindowColor());
649 0 : m_pTitleFT->set_height_request(m_pTitleFT->get_preferred_size().Height() + 48);
650 :
651 0 : m_pOkBtn->SetClickHdl( LINK( this, SaveDialog, OKButtonHdl ) );
652 0 : m_pFileListLB->SetControlBackground( rStyleSettings.GetDialogColor() );
653 :
654 : // fill listbox with current open documents
655 0 : m_pFileListLB->Clear();
656 :
657 0 : TURLList& pURLs = m_pCore->getURLListAccess();
658 0 : TURLList::const_iterator pIt;
659 :
660 0 : for ( pIt = pURLs.begin();
661 0 : pIt != pURLs.end() ;
662 : ++pIt )
663 : {
664 0 : const TURLInfo& rInfo = *pIt;
665 0 : m_pFileListLB->InsertEntry( rInfo.DisplayName, rInfo.StandardImage );
666 : }
667 0 : }
668 :
669 0 : SaveDialog::~SaveDialog()
670 : {
671 0 : disposeOnce();
672 0 : }
673 :
674 0 : void SaveDialog::dispose()
675 : {
676 0 : m_pTitleFT.clear();
677 0 : m_pFileListLB.clear();
678 0 : m_pOkBtn.clear();
679 0 : Dialog::dispose();
680 0 : }
681 :
682 0 : IMPL_LINK_NOARG(SaveDialog, OKButtonHdl)
683 : {
684 : // start crash-save with progress
685 0 : ScopedVclPtrInstance< SaveProgressDialog > pProgress(this, m_pCore);
686 0 : short nResult = pProgress->Execute();
687 0 : pProgress.reset();
688 :
689 : // if "CANCEL" => return "CANCEL"
690 : // if "OK" => "AUTOLUNCH" always !
691 0 : if (nResult == DLG_RET_OK)
692 0 : nResult = DLG_RET_OK_AUTOLUNCH;
693 :
694 0 : EndDialog(nResult);
695 0 : return 0;
696 : }
697 :
698 0 : SaveProgressDialog::SaveProgressDialog(vcl::Window* pParent, RecoveryCore* pCore)
699 : : ModalDialog(pParent, "DocRecoveryProgressDialog",
700 : "svx/ui/docrecoveryprogressdialog.ui")
701 0 : , m_pCore(pCore)
702 : {
703 0 : get(m_pProgrParent, "progress");
704 0 : Size aSize(LogicToPixel(Size(SAVEPROGR_CONTROLWIDTH, PROGR_HEIGHT)));
705 0 : m_pProgrParent->set_width_request(aSize.Width());
706 0 : m_pProgrParent->set_height_request(aSize.Height());
707 :
708 0 : PluginProgress* pProgress = new PluginProgress(m_pProgrParent, pCore->getComponentContext());
709 0 : m_xProgress = css::uno::Reference< css::task::XStatusIndicator >(static_cast< css::task::XStatusIndicator* >(pProgress), css::uno::UNO_QUERY_THROW);
710 0 : }
711 :
712 0 : SaveProgressDialog::~SaveProgressDialog()
713 : {
714 0 : disposeOnce();
715 0 : }
716 :
717 0 : void SaveProgressDialog::dispose()
718 : {
719 0 : m_pProgrParent.clear();
720 0 : ModalDialog::dispose();
721 0 : }
722 :
723 0 : short SaveProgressDialog::Execute()
724 : {
725 0 : ::SolarMutexGuard aLock;
726 :
727 0 : m_pCore->setProgressHandler(m_xProgress);
728 0 : m_pCore->setUpdateListener(this);
729 0 : m_pCore->doEmergencySave();
730 0 : short nRet = ModalDialog::Execute();
731 0 : m_pCore->setUpdateListener(0);
732 0 : return nRet;
733 : }
734 :
735 0 : void SaveProgressDialog::updateItems()
736 : {
737 0 : }
738 :
739 :
740 0 : void SaveProgressDialog::stepNext(TURLInfo* )
741 : {
742 : /* TODO
743 :
744 : if m_pCore would have a member m_mCurrentItem, you could see,
745 : who is current, who is next ... You can show this information
746 : in progress report FixText
747 : */
748 0 : }
749 :
750 :
751 0 : void SaveProgressDialog::start()
752 : {
753 0 : }
754 :
755 :
756 0 : void SaveProgressDialog::end()
757 : {
758 0 : EndDialog(DLG_RET_OK);
759 0 : }
760 :
761 :
762 0 : RecovDocListEntry::RecovDocListEntry( SvTreeListEntry* pEntry,
763 : sal_uInt16 nFlags,
764 : const OUString& sText )
765 0 : : SvLBoxString( pEntry, nFlags, sText )
766 : {
767 0 : }
768 :
769 :
770 0 : void RecovDocListEntry::Paint(const Point& aPos, SvTreeListBox& aDevice, vcl::RenderContext& rRenderContext,
771 : const SvViewDataEntry* /*pView*/, const SvTreeListEntry& rEntry)
772 : {
773 0 : const Image* pImg = 0;
774 0 : const OUString* pTxt = 0;
775 0 : RecovDocList* pList = static_cast<RecovDocList*>(&aDevice);
776 :
777 0 : TURLInfo* pInfo = static_cast<TURLInfo*>(rEntry.GetUserData());
778 0 : switch (pInfo->RecoveryState)
779 : {
780 : case E_SUCCESSFULLY_RECOVERED:
781 : {
782 0 : pImg = &pList->m_aGreenCheckImg;
783 0 : pTxt = &pList->m_aSuccessRecovStr;
784 : }
785 0 : break;
786 :
787 : case E_ORIGINAL_DOCUMENT_RECOVERED: // TODO must be renamed into ORIGINAL DOCUMENT recovered! Because its marked as yellow
788 : {
789 0 : pImg = &pList->m_aYellowCheckImg;
790 0 : pTxt = &pList->m_aOrigDocRecovStr;
791 : }
792 0 : break;
793 :
794 : case E_RECOVERY_FAILED:
795 : {
796 0 : pImg = &pList->m_aRedCrossImg;
797 0 : pTxt = &pList->m_aRecovFailedStr;
798 : }
799 0 : break;
800 :
801 : case E_RECOVERY_IS_IN_PROGRESS:
802 : {
803 0 : pImg = 0;
804 0 : pTxt = &pList->m_aRecovInProgrStr;
805 : }
806 0 : break;
807 :
808 : case E_NOT_RECOVERED_YET:
809 : {
810 0 : pImg = 0;
811 0 : pTxt = &pList->m_aNotRecovYetStr;
812 : }
813 0 : break;
814 : }
815 :
816 0 : if (pImg)
817 0 : rRenderContext.DrawImage(aPos, *pImg);
818 :
819 0 : if (pTxt)
820 : {
821 0 : Point aPnt(aPos);
822 0 : aPnt.X() += pList->m_aGreenCheckImg.GetSizePixel().Width();
823 0 : aPnt.X() += 10;
824 0 : rRenderContext.DrawText(aPnt, *pTxt);
825 : }
826 0 : }
827 :
828 0 : RecovDocList::RecovDocList(SvSimpleTableContainer& rParent, ResMgr &rResMgr)
829 : : SvSimpleTable ( rParent )
830 : , m_aGreenCheckImg ( ResId(RID_SVXIMG_GREENCHECK, rResMgr ) )
831 : , m_aYellowCheckImg ( ResId(RID_SVXIMG_YELLOWCHECK, rResMgr ) )
832 : , m_aRedCrossImg ( ResId(RID_SVXIMG_REDCROSS, rResMgr ) )
833 : , m_aSuccessRecovStr ( ResId(RID_SVXSTR_SUCCESSRECOV, rResMgr ) )
834 : , m_aOrigDocRecovStr ( ResId(RID_SVXSTR_ORIGDOCRECOV, rResMgr ) )
835 : , m_aRecovFailedStr ( ResId(RID_SVXSTR_RECOVFAILED, rResMgr ) )
836 : , m_aRecovInProgrStr ( ResId(RID_SVXSTR_RECOVINPROGR, rResMgr ) )
837 0 : , m_aNotRecovYetStr ( ResId(RID_SVXSTR_NOTRECOVYET, rResMgr ) )
838 : {
839 0 : }
840 :
841 0 : void RecovDocList::InitEntry(SvTreeListEntry* pEntry,
842 : const OUString& rText,
843 : const Image& rImage1,
844 : const Image& rImage2,
845 : SvLBoxButtonKind eButtonKind)
846 : {
847 0 : SvTabListBox::InitEntry(pEntry, rText, rImage1, rImage2, eButtonKind);
848 : DBG_ASSERT( TabCount() == 2, "*RecovDocList::InitEntry(): structure missmatch" );
849 :
850 0 : SvLBoxString* pCol = static_cast<SvLBoxString*>(pEntry->GetItem(2));
851 0 : RecovDocListEntry* p = new RecovDocListEntry(pEntry, 0, pCol->GetText());
852 0 : pEntry->ReplaceItem(p, 2);
853 0 : }
854 :
855 :
856 0 : short impl_askUserForWizardCancel(vcl::Window* pParent, sal_Int16 nRes)
857 : {
858 0 : ScopedVclPtrInstance< MessageDialog > aQuery(pParent, SVX_RES(nRes), VCL_MESSAGE_QUESTION, VCL_BUTTONS_YES_NO);
859 0 : if (aQuery->Execute() == RET_YES)
860 0 : return DLG_RET_OK;
861 : else
862 0 : return DLG_RET_CANCEL;
863 : }
864 :
865 0 : RecoveryDialog::RecoveryDialog(vcl::Window* pParent, RecoveryCore* pCore)
866 : : Dialog(pParent, "DocRecoveryRecoverDialog",
867 : "svx/ui/docrecoveryrecoverdialog.ui")
868 0 : , m_aTitleRecoveryInProgress(SVX_RESSTR(RID_SVXSTR_RECOVERY_INPROGRESS))
869 0 : , m_aRecoveryOnlyFinish (SVX_RESSTR(RID_SVXSTR_RECOVERYONLY_FINISH))
870 0 : , m_aRecoveryOnlyFinishDescr(SVX_RESSTR(RID_SVXSTR_RECOVERYONLY_FINISH_DESCR))
871 : , m_pCore(pCore)
872 : , m_eRecoveryState(RecoveryDialog::E_RECOVERY_PREPARED)
873 : , m_bWaitForCore(false)
874 0 : , m_bWasRecoveryStarted(false)
875 : {
876 0 : get(m_pTitleFT, "title");
877 0 : get(m_pDescrFT, "desc");
878 0 : get(m_pProgrParent, "progress");
879 0 : m_pProgrParent->set_height_request(LogicToPixel(Size(0, PROGR_HEIGHT), MAP_APPFONT).Height());
880 0 : get(m_pNextBtn, "next");
881 0 : get(m_pCancelBtn, "cancel");
882 :
883 0 : SvSimpleTableContainer* pFileListLBContainer = get<SvSimpleTableContainer>("filelist");
884 0 : Size aSize(LogicToPixel(Size(RECOV_CONTROLWIDTH, RECOV_FILELISTHEIGHT), MAP_APPFONT));
885 0 : pFileListLBContainer->set_width_request(aSize.Width());
886 0 : pFileListLBContainer->set_height_request(aSize.Height());
887 0 : m_pFileListLB = VclPtr<RecovDocList>::Create(*pFileListLBContainer, DIALOG_MGR());
888 :
889 : static long nTabs[] = { 2, 0, 40*RECOV_CONTROLWIDTH/100 };
890 0 : m_pFileListLB->SetTabs( &nTabs[0] );
891 0 : m_pFileListLB->InsertHeaderEntry(get<FixedText>("nameft")->GetText() + "\t" + get<FixedText>("statusft")->GetText());
892 :
893 0 : PluginProgress* pProgress = new PluginProgress(m_pProgrParent, pCore->getComponentContext());
894 0 : m_xProgress = css::uno::Reference< css::task::XStatusIndicator >(static_cast< css::task::XStatusIndicator* >(pProgress), css::uno::UNO_QUERY_THROW);
895 :
896 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
897 0 : m_pTitleFT->SetBackground(rStyleSettings.GetWindowColor());
898 0 : m_pTitleFT->set_height_request(m_pTitleFT->get_preferred_size().Height() + 48);
899 :
900 0 : m_pFileListLB->SetBackground( rStyleSettings.GetDialogColor() );
901 :
902 0 : m_pNextBtn->Enable(true);
903 0 : m_pNextBtn->SetClickHdl( LINK( this, RecoveryDialog, NextButtonHdl ) );
904 0 : m_pCancelBtn->SetClickHdl( LINK( this, RecoveryDialog, CancelButtonHdl ) );
905 :
906 : // fill list box first time
907 0 : TURLList& pURLList = m_pCore->getURLListAccess();
908 0 : TURLList::const_iterator pIt;
909 0 : for ( pIt = pURLList.begin();
910 0 : pIt != pURLList.end() ;
911 : ++pIt )
912 : {
913 0 : const TURLInfo& rInfo = *pIt;
914 :
915 0 : OUString sName( rInfo.DisplayName );
916 0 : sName += "\t";
917 0 : sName += impl_getStatusString( rInfo );
918 0 : SvTreeListEntry* pEntry = m_pFileListLB->InsertEntry(sName, rInfo.StandardImage, rInfo.StandardImage);
919 0 : pEntry->SetUserData(const_cast<TURLInfo *>(&rInfo));
920 0 : }
921 :
922 : // mark first item
923 0 : SvTreeListEntry* pFirst = m_pFileListLB->First();
924 0 : if (pFirst)
925 0 : m_pFileListLB->SetCursor(pFirst, true);
926 0 : }
927 :
928 0 : RecoveryDialog::~RecoveryDialog()
929 : {
930 0 : disposeOnce();
931 0 : }
932 :
933 0 : void RecoveryDialog::dispose()
934 : {
935 0 : m_pFileListLB.disposeAndClear();
936 0 : m_pTitleFT.clear();
937 0 : m_pDescrFT.clear();
938 0 : m_pProgrParent.clear();
939 0 : m_pNextBtn.clear();
940 0 : m_pCancelBtn.clear();
941 0 : Dialog::dispose();
942 0 : }
943 :
944 0 : short RecoveryDialog::execute()
945 : {
946 0 : ::SolarMutexGuard aSolarLock;
947 :
948 0 : switch (m_eRecoveryState)
949 : {
950 : case RecoveryDialog::E_RECOVERY_IN_PROGRESS :
951 : {
952 : // user decided to start recovery ...
953 0 : m_bWasRecoveryStarted = true;
954 : // do it asynchronous (to allow repaints)
955 : // and wait for this asynchronous operation.
956 0 : m_pDescrFT->SetText( m_aTitleRecoveryInProgress );
957 0 : m_pNextBtn->Enable(false);
958 0 : m_pCancelBtn->Enable(false);
959 0 : m_pCore->setProgressHandler(m_xProgress);
960 0 : m_pCore->setUpdateListener(this);
961 0 : m_pCore->doRecovery();
962 :
963 0 : m_bWaitForCore = true;
964 0 : while(m_bWaitForCore)
965 0 : Application::Yield();
966 :
967 0 : m_pCore->setUpdateListener(0);
968 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_CORE_DONE;
969 0 : return execute();
970 : }
971 :
972 : case RecoveryDialog::E_RECOVERY_CORE_DONE :
973 : {
974 : // the core finished it's task.
975 : // let the user decide the next step.
976 0 : m_pDescrFT->SetText(m_aRecoveryOnlyFinishDescr);
977 0 : m_pNextBtn->SetText(m_aRecoveryOnlyFinish);
978 0 : m_pNextBtn->Enable(true);
979 0 : m_pCancelBtn->Enable(false);
980 0 : return 0;
981 : }
982 :
983 : case RecoveryDialog::E_RECOVERY_DONE :
984 : {
985 : // All documents was reovered.
986 : // User decided to step to the "next" wizard page.
987 : // Do it ... but check first, if there exist some
988 : // failed recovery documents. They must be saved to
989 : // a user selected directrory.
990 0 : short nRet = DLG_RET_UNKNOWN;
991 0 : ScopedVclPtrInstance< BrokenRecoveryDialog > pBrokenRecoveryDialog(this, m_pCore, !m_bWasRecoveryStarted);
992 0 : OUString sSaveDir = pBrokenRecoveryDialog->getSaveDirURL(); // get the default dir
993 0 : if (pBrokenRecoveryDialog->isExecutionNeeded())
994 : {
995 0 : nRet = pBrokenRecoveryDialog->Execute();
996 0 : sSaveDir = pBrokenRecoveryDialog->getSaveDirURL();
997 : }
998 0 : pBrokenRecoveryDialog.reset();
999 :
1000 0 : switch(nRet)
1001 : {
1002 : // no broken temp files exists
1003 : // step to the next wizard page
1004 : case DLG_RET_UNKNOWN :
1005 : {
1006 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1007 0 : return DLG_RET_OK;
1008 : }
1009 :
1010 : // user decided to save the broken temp files
1011 : // do and forget it
1012 : // step to the next wizard page
1013 : case DLG_RET_OK :
1014 : {
1015 0 : m_pCore->saveBrokenTempEntries(sSaveDir);
1016 0 : m_pCore->forgetBrokenTempEntries();
1017 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1018 0 : return DLG_RET_OK;
1019 : }
1020 :
1021 : // user decided to ignore broken temp files.
1022 : // Ask it again ... may be this decision was wrong.
1023 : // Results:
1024 : // IGNORE => remove broken temp files
1025 : // => step to the next wizard page
1026 : // CANCEL => step back to the recovery page
1027 : case DLG_RET_CANCEL :
1028 : {
1029 : // TODO ask user ...
1030 0 : m_pCore->forgetBrokenTempEntries();
1031 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1032 0 : return DLG_RET_OK;
1033 : }
1034 : }
1035 :
1036 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1037 0 : return DLG_RET_OK;
1038 : }
1039 :
1040 : case RecoveryDialog::E_RECOVERY_CANCELED :
1041 : {
1042 : // "YES" => break recovery
1043 : // But there exist different states, where "cancel" can be called.
1044 : // Handle it different.
1045 0 : if (m_bWasRecoveryStarted)
1046 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED_AFTERWARDS;
1047 : else
1048 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED_BEFORE;
1049 0 : return execute();
1050 : }
1051 :
1052 : case RecoveryDialog::E_RECOVERY_CANCELED_BEFORE :
1053 : case RecoveryDialog::E_RECOVERY_CANCELED_AFTERWARDS :
1054 : {
1055 : // We have to check if there exists some temp. files.
1056 : // They should be saved to a user defined location.
1057 : // If no temp files exists or user decided to ignore it ...
1058 : // we have to remove all recovery/session data anyway!
1059 0 : short nRet = DLG_RET_UNKNOWN;
1060 0 : ScopedVclPtrInstance< BrokenRecoveryDialog > pBrokenRecoveryDialog(this, m_pCore, !m_bWasRecoveryStarted);
1061 0 : OUString sSaveDir = pBrokenRecoveryDialog->getSaveDirURL(); // get the default save location
1062 :
1063 : // dialog itself checks if there is a need to copy files for this mode.
1064 : // It uses the information m_bWasRecoveryStarted doing so.
1065 0 : if (pBrokenRecoveryDialog->isExecutionNeeded())
1066 : {
1067 0 : nRet = pBrokenRecoveryDialog->Execute();
1068 0 : sSaveDir = pBrokenRecoveryDialog->getSaveDirURL();
1069 : }
1070 0 : pBrokenRecoveryDialog.reset();
1071 :
1072 : // Possible states:
1073 : // a) nRet == DLG_RET_UNKNOWN
1074 : // dialog was not shown ...
1075 : // because there exists no temp file for copy.
1076 : // => remove all recovery data
1077 : // b) nRet == DLG_RET_OK
1078 : // dialog was shown ...
1079 : // user decided to save temp files
1080 : // => save all OR broken temp files (depends from the time, where cancel was called)
1081 : // => remove all recovery data
1082 : // c) nRet == DLG_RET_CANCEL
1083 : // dialog was shown ...
1084 : // user decided to ignore temp files
1085 : // => remove all recovery data
1086 : // => a)/c) are the same ... b) has one additional operation
1087 :
1088 : // b)
1089 0 : if (nRet == DLG_RET_OK)
1090 : {
1091 0 : if (m_bWasRecoveryStarted)
1092 0 : m_pCore->saveBrokenTempEntries(sSaveDir);
1093 : else
1094 0 : m_pCore->saveAllTempEntries(sSaveDir);
1095 : }
1096 :
1097 : // a,b,c)
1098 0 : if (m_bWasRecoveryStarted)
1099 0 : m_pCore->forgetBrokenRecoveryEntries();
1100 : else
1101 0 : m_pCore->forgetAllRecoveryEntries();
1102 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
1103 :
1104 : // THERE IS NO WAY BACK. see impl_askUserForWizardCancel()!
1105 0 : return DLG_RET_CANCEL;
1106 : }
1107 : }
1108 :
1109 : // should never be reached .-)
1110 : OSL_FAIL("Should never be reached!");
1111 0 : return DLG_RET_OK;
1112 : }
1113 :
1114 0 : void RecoveryDialog::start()
1115 : {
1116 0 : }
1117 :
1118 0 : void RecoveryDialog::updateItems()
1119 : {
1120 0 : sal_uIntPtr c = m_pFileListLB->GetEntryCount();
1121 0 : sal_uIntPtr i = 0;
1122 0 : for ( i=0; i<c; ++i )
1123 : {
1124 0 : SvTreeListEntry* pEntry = m_pFileListLB->GetEntry(i);
1125 0 : if ( !pEntry )
1126 0 : continue;
1127 :
1128 0 : TURLInfo* pInfo = static_cast<TURLInfo*>(pEntry->GetUserData());
1129 0 : if ( !pInfo )
1130 0 : continue;
1131 :
1132 0 : OUString sStatus = impl_getStatusString( *pInfo );
1133 0 : if ( !sStatus.isEmpty() )
1134 0 : m_pFileListLB->SetEntryText( sStatus, pEntry, 1 );
1135 0 : }
1136 :
1137 0 : m_pFileListLB->Invalidate();
1138 0 : m_pFileListLB->Update();
1139 0 : }
1140 :
1141 :
1142 0 : void RecoveryDialog::stepNext(TURLInfo* pItem)
1143 : {
1144 0 : sal_uIntPtr c = m_pFileListLB->GetEntryCount();
1145 0 : sal_uIntPtr i = 0;
1146 0 : for (i=0; i<c; ++i)
1147 : {
1148 0 : SvTreeListEntry* pEntry = m_pFileListLB->GetEntry(i);
1149 0 : if (!pEntry)
1150 0 : continue;
1151 :
1152 0 : TURLInfo* pInfo = static_cast<TURLInfo*>(pEntry->GetUserData());
1153 0 : if (pInfo->ID != pItem->ID)
1154 0 : continue;
1155 :
1156 0 : m_pFileListLB->SetCursor(pEntry, true);
1157 0 : m_pFileListLB->MakeVisible(pEntry);
1158 0 : m_pFileListLB->Invalidate();
1159 0 : m_pFileListLB->Update();
1160 0 : break;
1161 : }
1162 0 : }
1163 :
1164 0 : void RecoveryDialog::end()
1165 : {
1166 0 : m_bWaitForCore = false;
1167 0 : }
1168 :
1169 0 : IMPL_LINK_NOARG(RecoveryDialog, NextButtonHdl)
1170 : {
1171 0 : switch (m_eRecoveryState)
1172 : {
1173 : case RecoveryDialog::E_RECOVERY_PREPARED:
1174 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_IN_PROGRESS;
1175 0 : execute();
1176 0 : break;
1177 : case RecoveryDialog::E_RECOVERY_CORE_DONE:
1178 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_DONE;
1179 0 : execute();
1180 0 : break;
1181 : }
1182 :
1183 0 : if (m_eRecoveryState == RecoveryDialog::E_RECOVERY_HANDLED)
1184 : {
1185 0 : EndDialog(DLG_RET_OK);
1186 0 : return DLG_RET_OK;
1187 : }
1188 :
1189 0 : return 0;
1190 : }
1191 :
1192 0 : IMPL_LINK_NOARG(RecoveryDialog, CancelButtonHdl)
1193 : {
1194 0 : switch (m_eRecoveryState)
1195 : {
1196 : case RecoveryDialog::E_RECOVERY_PREPARED:
1197 0 : if (impl_askUserForWizardCancel(this, RID_SVXSTR_QUERY_EXIT_RECOVERY) != DLG_RET_CANCEL)
1198 : {
1199 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED;
1200 0 : execute();
1201 : }
1202 0 : break;
1203 : case RecoveryDialog::E_RECOVERY_CORE_DONE:
1204 0 : m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED;
1205 0 : execute();
1206 0 : break;
1207 : }
1208 :
1209 0 : if (m_eRecoveryState == RecoveryDialog::E_RECOVERY_HANDLED)
1210 : {
1211 0 : EndDialog(DLG_RET_CANCEL);
1212 0 : return DLG_RET_CANCEL;
1213 : }
1214 :
1215 0 : return 0;
1216 : }
1217 :
1218 0 : OUString RecoveryDialog::impl_getStatusString( const TURLInfo& rInfo ) const
1219 : {
1220 0 : OUString sStatus;
1221 0 : switch ( rInfo.RecoveryState )
1222 : {
1223 : case E_SUCCESSFULLY_RECOVERED :
1224 0 : sStatus = m_pFileListLB->m_aSuccessRecovStr;
1225 0 : break;
1226 : case E_ORIGINAL_DOCUMENT_RECOVERED :
1227 0 : sStatus = m_pFileListLB->m_aOrigDocRecovStr;
1228 0 : break;
1229 : case E_RECOVERY_FAILED :
1230 0 : sStatus = m_pFileListLB->m_aRecovFailedStr;
1231 0 : break;
1232 : case E_RECOVERY_IS_IN_PROGRESS :
1233 0 : sStatus = m_pFileListLB->m_aRecovInProgrStr;
1234 0 : break;
1235 : case E_NOT_RECOVERED_YET :
1236 0 : sStatus = m_pFileListLB->m_aNotRecovYetStr;
1237 0 : break;
1238 : default:
1239 0 : break;
1240 : }
1241 0 : return sStatus;
1242 : }
1243 :
1244 0 : BrokenRecoveryDialog::BrokenRecoveryDialog(vcl::Window* pParent ,
1245 : RecoveryCore* pCore ,
1246 : bool bBeforeRecovery)
1247 : : ModalDialog ( pParent, "DocRecoveryBrokenDialog", "svx/ui/docrecoverybrokendialog.ui" )
1248 : , m_pCore ( pCore )
1249 : , m_bBeforeRecovery (bBeforeRecovery)
1250 0 : , m_bExecutionNeeded(false)
1251 : {
1252 0 : get(m_pFileListLB, "filelist");
1253 0 : get(m_pSaveDirED, "savedir");
1254 0 : get(m_pSaveDirBtn, "change");
1255 0 : get(m_pOkBtn, "save");
1256 0 : get(m_pCancelBtn, "cancel");
1257 :
1258 0 : m_pSaveDirBtn->SetClickHdl( LINK( this, BrokenRecoveryDialog, SaveButtonHdl ) );
1259 0 : m_pOkBtn->SetClickHdl( LINK( this, BrokenRecoveryDialog, OkButtonHdl ) );
1260 0 : m_pCancelBtn->SetClickHdl( LINK( this, BrokenRecoveryDialog, CancelButtonHdl ) );
1261 :
1262 0 : m_sSavePath = SvtPathOptions().GetWorkPath();
1263 0 : INetURLObject aObj( m_sSavePath );
1264 0 : OUString sPath;
1265 0 : ::utl::LocalFileHelper::ConvertURLToSystemPath( aObj.GetMainURL( INetURLObject::NO_DECODE ), sPath );
1266 0 : m_pSaveDirED->SetText( sPath );
1267 :
1268 0 : impl_refresh();
1269 0 : }
1270 :
1271 0 : BrokenRecoveryDialog::~BrokenRecoveryDialog()
1272 : {
1273 0 : disposeOnce();
1274 0 : }
1275 :
1276 0 : void BrokenRecoveryDialog::dispose()
1277 : {
1278 0 : m_pFileListLB.clear();
1279 0 : m_pSaveDirED.clear();
1280 0 : m_pSaveDirBtn.clear();
1281 0 : m_pOkBtn.clear();
1282 0 : m_pCancelBtn.clear();
1283 0 : ModalDialog::dispose();
1284 0 : }
1285 :
1286 :
1287 0 : void BrokenRecoveryDialog::impl_refresh()
1288 : {
1289 0 : m_bExecutionNeeded = false;
1290 0 : TURLList& pURLList = m_pCore->getURLListAccess();
1291 0 : TURLList::const_iterator pIt;
1292 0 : for ( pIt = pURLList.begin();
1293 0 : pIt != pURLList.end() ;
1294 : ++pIt )
1295 : {
1296 0 : const TURLInfo& rInfo = *pIt;
1297 :
1298 0 : if (m_bBeforeRecovery)
1299 : {
1300 : // "Cancel" before recovery ->
1301 : // search for any temp files!
1302 0 : if (rInfo.TempURL.isEmpty())
1303 0 : continue;
1304 : }
1305 : else
1306 : {
1307 : // "Cancel" after recovery ->
1308 : // search for broken temp files
1309 0 : if (!RecoveryCore::isBrokenTempEntry(rInfo))
1310 0 : continue;
1311 : }
1312 :
1313 0 : m_bExecutionNeeded = true;
1314 :
1315 0 : sal_uInt16 nPos = m_pFileListLB->InsertEntry(rInfo.DisplayName, rInfo.StandardImage );
1316 0 : m_pFileListLB->SetEntryData( nPos, const_cast<TURLInfo *>(&rInfo) );
1317 : }
1318 0 : m_sSavePath.clear();
1319 0 : m_pOkBtn->GrabFocus();
1320 0 : }
1321 :
1322 :
1323 0 : bool BrokenRecoveryDialog::isExecutionNeeded()
1324 : {
1325 0 : return m_bExecutionNeeded;
1326 : }
1327 :
1328 :
1329 0 : OUString BrokenRecoveryDialog::getSaveDirURL()
1330 : {
1331 0 : return m_sSavePath;
1332 : }
1333 :
1334 :
1335 0 : IMPL_LINK_NOARG(BrokenRecoveryDialog, OkButtonHdl)
1336 : {
1337 0 : OUString sPhysicalPath = comphelper::string::strip(m_pSaveDirED->GetText(), ' ');
1338 0 : OUString sURL;
1339 0 : ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sPhysicalPath, sURL );
1340 0 : m_sSavePath = sURL;
1341 0 : while (m_sSavePath.isEmpty())
1342 0 : impl_askForSavePath();
1343 :
1344 0 : EndDialog(DLG_RET_OK);
1345 0 : return 0;
1346 : }
1347 :
1348 :
1349 0 : IMPL_LINK_NOARG(BrokenRecoveryDialog, CancelButtonHdl)
1350 : {
1351 0 : EndDialog(DLG_RET_CANCEL);
1352 0 : return 0;
1353 : }
1354 :
1355 :
1356 0 : IMPL_LINK_NOARG(BrokenRecoveryDialog, SaveButtonHdl)
1357 : {
1358 0 : impl_askForSavePath();
1359 0 : return 0;
1360 : }
1361 :
1362 :
1363 0 : void BrokenRecoveryDialog::impl_askForSavePath()
1364 : {
1365 : css::uno::Reference< css::ui::dialogs::XFolderPicker2 > xFolderPicker =
1366 0 : css::ui::dialogs::FolderPicker::create( m_pCore->getComponentContext() );
1367 :
1368 0 : INetURLObject aURL(m_sSavePath, INetProtocol::File);
1369 0 : xFolderPicker->setDisplayDirectory(aURL.GetMainURL(INetURLObject::NO_DECODE));
1370 0 : short nRet = xFolderPicker->execute();
1371 0 : if (nRet == css::ui::dialogs::ExecutableDialogResults::OK)
1372 : {
1373 0 : m_sSavePath = xFolderPicker->getDirectory();
1374 0 : OUString sPath;
1375 0 : ::utl::LocalFileHelper::ConvertURLToSystemPath( m_sSavePath, sPath );
1376 0 : m_pSaveDirED->SetText( sPath );
1377 0 : }
1378 0 : }
1379 :
1380 : }
1381 390 : }
1382 :
1383 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|