LibreOffice Module svx (master) 1
docrecovery.cxx
Go to the documentation of this file.
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 <svx/dialmgr.hxx>
21#include <svx/strings.hrc>
22#include <bitmaps.hlst>
23#include <docrecovery.hxx>
24
27#include <comphelper/string.hxx>
28#include <o3tl/safeint.hxx>
29#include <svtools/imagemgr.hxx>
31#include <tools/urlobj.hxx>
32#include <vcl/weld.hxx>
33#include <vcl/svapp.hxx>
34
35#include <com/sun/star/util/URL.hpp>
36#include <com/sun/star/util/XURLTransformer.hpp>
37#include <com/sun/star/frame/theAutoRecovery.hpp>
38#include <com/sun/star/ui/dialogs/XFolderPicker2.hpp>
39#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
40#include <com/sun/star/util/URLTransformer.hpp>
41#include <osl/file.hxx>
43
45{
46
47using namespace ::osl;
48
49RecoveryCore::RecoveryCore(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
50 bool bUsedForSaving)
51 : m_xContext ( rxContext )
52 , m_pListener ( nullptr )
53 , m_bListenForSaving(bUsedForSaving)
54{
56}
57
58
60{
62}
63
64
65const css::uno::Reference< css::uno::XComponentContext >& RecoveryCore::getComponentContext() const
66{
67 return m_xContext;
68}
69
70
72{
73 return m_lURLs;
74}
75
76
78{
79 if (rInfo.TempURL.isEmpty())
80 return false;
81
82 // Note: If the original files was recovery ... but a temp file
83 // exists ... an error inside the temp file exists!
84 if (
85 (rInfo.RecoveryState != E_RECOVERY_FAILED ) &&
87 )
88 return false;
89
90 return true;
91}
92
93
94void RecoveryCore::saveBrokenTempEntries(const OUString& rPath)
95{
96 if (rPath.isEmpty())
97 return;
98
99 if (!m_xRealCore.is())
100 return;
101
102 // prepare all needed parameters for the following dispatch() request.
103 css::util::URL aCopyURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_BACKUP);
104 css::uno::Sequence< css::beans::PropertyValue > lCopyArgs(3);
105 auto plCopyArgs = lCopyArgs.getArray();
106 plCopyArgs[0].Name = PROP_DISPATCHASYNCHRON;
107 plCopyArgs[0].Value <<= false;
108 plCopyArgs[1].Name = PROP_SAVEPATH;
109 plCopyArgs[1].Value <<= rPath;
110 plCopyArgs[2].Name = PROP_ENTRYID;
111 // lCopyArgs[2].Value will be changed during next loop...
112
113 // work on a copied list only...
114 // Reason: We will get notifications from the core for every
115 // changed or removed element. And that will change our m_lURLs list.
116 // That's not a good idea, if we use a stl iterator inbetween .-)
117 TURLList lURLs = m_lURLs;
118 for (const TURLInfo& rInfo : lURLs)
119 {
121 continue;
122
123 plCopyArgs[2].Value <<= rInfo.ID;
124 m_xRealCore->dispatch(aCopyURL, lCopyArgs);
125 }
126}
127
128
129void RecoveryCore::saveAllTempEntries(const OUString& rPath)
130{
131 if (rPath.isEmpty())
132 return;
133
134 if (!m_xRealCore.is())
135 return;
136
137 // prepare all needed parameters for the following dispatch() request.
138 css::util::URL aCopyURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_BACKUP);
139 css::uno::Sequence< css::beans::PropertyValue > lCopyArgs(3);
140 auto plCopyArgs = lCopyArgs.getArray();
141 plCopyArgs[0].Name = PROP_DISPATCHASYNCHRON;
142 plCopyArgs[0].Value <<= false;
143 plCopyArgs[1].Name = PROP_SAVEPATH;
144 plCopyArgs[1].Value <<= rPath;
145 plCopyArgs[2].Name = PROP_ENTRYID;
146 // lCopyArgs[2].Value will be changed during next loop ...
147
148 // work on a copied list only ...
149 // Reason: We will get notifications from the core for every
150 // changed or removed element. And that will change our m_lURLs list.
151 // That's not a good idea, if we use a stl iterator inbetween .-)
152 TURLList lURLs = m_lURLs;
153 for (const TURLInfo& rInfo : lURLs)
154 {
155 if (rInfo.TempURL.isEmpty())
156 continue;
157
158 plCopyArgs[2].Value <<= rInfo.ID;
159 m_xRealCore->dispatch(aCopyURL, lCopyArgs);
160 }
161}
162
163
165{
166 if (!m_xRealCore.is())
167 return;
168
169 css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
170 css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
171 auto plRemoveArgs = lRemoveArgs.getArray();
172 plRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
173 plRemoveArgs[0].Value <<= false;
174 plRemoveArgs[1].Name = PROP_ENTRYID;
175 // lRemoveArgs[1].Value will be changed during next loop ...
176
177 // work on a copied list only ...
178 // Reason: We will get notifications from the core for every
179 // changed or removed element. And that will change our m_lURLs list.
180 // That's not a good idea, if we use a stl iterator inbetween .-)
181 TURLList lURLs = m_lURLs;
182 for (const TURLInfo& rInfo : lURLs)
183 {
185 continue;
186
187 plRemoveArgs[1].Value <<= rInfo.ID;
188 m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
189 }
190}
191
192
194{
195 if (!m_xRealCore.is())
196 return;
197
198 css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
199 css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
200 auto plRemoveArgs = lRemoveArgs.getArray();
201 plRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
202 plRemoveArgs[0].Value <<= false;
203 plRemoveArgs[1].Name = PROP_ENTRYID;
204 // lRemoveArgs[1].Value will be changed during next loop ...
205
206 // work on a copied list only ...
207 // Reason: We will get notifications from the core for every
208 // changed or removed element. And that will change our m_lURLs list.
209 // That's not a good idea, if we use a stl iterator inbetween .-)
210 TURLList lURLs = m_lURLs;
211 for (const TURLInfo& rInfo : lURLs)
212 {
213 plRemoveArgs[1].Value <<= rInfo.ID;
214 m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
215 }
216}
217
218
220{
221 if (!m_xRealCore.is())
222 return;
223
224 css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
225 css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
226 auto plRemoveArgs = lRemoveArgs.getArray();
227 plRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
228 plRemoveArgs[0].Value <<= false;
229 plRemoveArgs[1].Name = PROP_ENTRYID;
230 // lRemoveArgs[1].Value will be changed during next loop ...
231
232 // work on a copied list only ...
233 // Reason: We will get notifications from the core for every
234 // changed or removed element. And that will change our m_lURLs list.
235 // That's not a good idea, if we use a stl iterator inbetween .-)
236 TURLList lURLs = m_lURLs;
237 for (const TURLInfo& rInfo : lURLs)
238 {
240 continue;
241
242 plRemoveArgs[1].Value <<= rInfo.ID;
243 m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
244 }
245}
246
247
248void RecoveryCore::setProgressHandler(const css::uno::Reference< css::task::XStatusIndicator >& xProgress)
249{
250 m_xProgress = xProgress;
251}
252
253
255{
256 m_pListener = pListener;
257}
258
259
261{
262 if (!m_xRealCore.is())
263 return;
264
266
267 css::uno::Sequence< css::beans::PropertyValue > lArgs{ comphelper::makePropertyValue(
268 PROP_DISPATCHASYNCHRON, false) };
269
270 m_xRealCore->dispatch(aURL, lArgs);
271}
272
273
275{
276 if (!m_xRealCore.is())
277 return;
278
280
281 css::uno::Sequence< css::beans::PropertyValue > lArgs{
284 };
285
286 m_xRealCore->dispatch(aURL, lArgs);
287}
288
289
291{
292 if (!m_xRealCore.is())
293 return;
294
296
297 css::uno::Sequence< css::beans::PropertyValue > lArgs{
300 };
301
302 m_xRealCore->dispatch(aURL, lArgs);
303}
304
305
307{
308 // ???
310
311 /* Attention:
312 Some of the following states can occur at the
313 same time. So we have to check for the "worst case" first!
314
315 DAMAGED -> INCOMPLETE -> HANDLED
316 */
317
318 // running ...
319 if (
320 (eDocState & EDocStates::TryLoadBackup ) ||
321 (eDocState & EDocStates::TryLoadOriginal)
322 )
323 eRecState = E_RECOVERY_IS_IN_PROGRESS;
324 // red
325 else if (eDocState & EDocStates::Damaged)
326 eRecState = E_RECOVERY_FAILED;
327 // yellow
328 else if (eDocState & EDocStates::Incomplete)
330 // green
331 else if (eDocState & EDocStates::Succeeded)
332 eRecState = E_SUCCESSFULLY_RECOVERED;
333
334 return eRecState;
335}
336
337
338void SAL_CALL RecoveryCore::statusChanged(const css::frame::FeatureStateEvent& aEvent)
339{
340 // a) special notification about start/stop async dispatch!
341 // FeatureDescriptor = "start" || "stop"
342 if (aEvent.FeatureDescriptor == RECOVERY_OPERATIONSTATE_START)
343 {
344 return;
345 }
346
347 if (aEvent.FeatureDescriptor == RECOVERY_OPERATIONSTATE_STOP)
348 {
349 if (m_pListener)
350 m_pListener->end();
351 return;
352 }
353
354 // b) normal notification about changed items
355 // FeatureDescriptor = "Update"
356 // State = List of information [seq< NamedValue >]
357 if (aEvent.FeatureDescriptor != RECOVERY_OPERATIONSTATE_UPDATE)
358 return;
359
361 TURLInfo aNew;
362
363 aNew.ID = lInfo.getUnpackedValueOrDefault(STATEPROP_ID , sal_Int32(0) );
364 aNew.DocState = static_cast<EDocStates>(lInfo.getUnpackedValueOrDefault(STATEPROP_STATE , sal_Int32(0) ));
365 aNew.OrgURL = lInfo.getUnpackedValueOrDefault(STATEPROP_ORGURL , OUString());
366 aNew.TempURL = lInfo.getUnpackedValueOrDefault(STATEPROP_TEMPURL , OUString());
369 aNew.DisplayName = lInfo.getUnpackedValueOrDefault(STATEPROP_TITLE , OUString());
370 aNew.Module = lInfo.getUnpackedValueOrDefault(STATEPROP_MODULE , OUString());
371
372 if (aNew.OrgURL.isEmpty()) {
373 // If there is no file URL, the window title is used for the display name.
374 // Remove any unwanted elements such as " - LibreOffice Writer".
375 sal_Int32 i = aNew.DisplayName.indexOf(" - ");
376 if (i > 0)
377 aNew.DisplayName = aNew.DisplayName.copy(0, i);
378 } else {
379 // If there is a file URL, parse out the filename part as the display name.
380 INetURLObject aOrgURL(aNew.OrgURL);
383 }
384
385 // search for already existing items and update her nState value ...
386 for (TURLInfo& aOld : m_lURLs)
387 {
388 if (aOld.ID == aNew.ID)
389 {
390 // change existing
391 aOld.DocState = aNew.DocState;
392 aOld.RecoveryState = RecoveryCore::mapDocState2RecoverState(aOld.DocState);
393 if (m_pListener)
394 {
396 m_pListener->stepNext(&aOld);
397 }
398 return;
399 }
400 }
401
402 // append as new one
403 // TODO think about matching Module name to a corresponding icon
404 OUString sURL = aNew.OrgURL;
405 if (sURL.isEmpty())
406 sURL = aNew.FactoryURL;
407 if (sURL.isEmpty())
408 sURL = aNew.TempURL;
409 if (sURL.isEmpty())
410 sURL = aNew.TemplateURL;
411 INetURLObject aURL(sURL);
413
414 /* set the right UI state for this item to NOT_RECOVERED_YET... because nDocState shows the state of
415 the last emergency save operation before and is interesting for the used recovery core service only...
416 for now! But if there is a further notification for this item (see lines above!) we must
417 map the doc state to an UI state. */
419
420 m_lURLs.push_back(aNew);
421
422 if (m_pListener)
424}
425
426
427void SAL_CALL RecoveryCore::disposing(const css::lang::EventObject& /*aEvent*/)
428{
429 m_xRealCore.clear();
430}
431
432
434{
435 // listening already initialized ?
436 if (m_xRealCore.is())
437 return;
438 m_xRealCore = css::frame::theAutoRecovery::get(m_xContext);
439
440 css::util::URL aURL;
443 else
445 css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
446 xParser->parseStrict(aURL);
447
448 /* Note: addStatusListener() call us synchronous back ... so we
449 will get the complete list of currently open documents! */
450 m_xRealCore->addStatusListener(static_cast< css::frame::XStatusListener* >(this), aURL);
451}
452
453
455{
456 // Ignore it, if this instance doesn't listen currently
457 if (!m_xRealCore.is())
458 return;
459
460 css::util::URL aURL;
463 else
465 css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
466 xParser->parseStrict(aURL);
467
468 m_xRealCore->removeStatusListener(static_cast< css::frame::XStatusListener* >(this), aURL);
469 m_xRealCore.clear();
470}
471
472
473css::util::URL RecoveryCore::impl_getParsedURL(const OUString& sURL)
474{
475 css::util::URL aURL;
476 aURL.Complete = sURL;
477
478 css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
479 xParser->parseStrict(aURL);
480
481 return aURL;
482}
483
485 : m_pProgressBar(pProgressBar)
486 , m_nRange(100)
487{
488}
489
491{
492}
493
495{
496 m_pProgressBar = nullptr;
497}
498
499void SAL_CALL PluginProgress::addEventListener(const css::uno::Reference< css::lang::XEventListener >& )
500{
501}
502
503void SAL_CALL PluginProgress::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& )
504{
505}
506
507void SAL_CALL PluginProgress::start(const OUString&, sal_Int32 nRange)
508{
509 m_nRange = nRange;
510 if (m_pProgressBar)
512}
513
514void SAL_CALL PluginProgress::end()
515{
516 if (m_pProgressBar)
518}
519
520void SAL_CALL PluginProgress::setText(const OUString& rText)
521{
522 if (m_pProgressBar)
523 m_pProgressBar->set_text(rText);
524}
525
526void SAL_CALL PluginProgress::setValue(sal_Int32 nValue)
527{
528 if (m_pProgressBar)
530}
531
533{
534 if (m_pProgressBar)
536}
537
539 : GenericDialogController(pParent, "svx/ui/docrecoverysavedialog.ui", "DocRecoverySaveDialog")
540 , m_pCore(pCore)
541 , m_xFileListLB(m_xBuilder->weld_tree_view("filelist"))
542 , m_xOkBtn(m_xBuilder->weld_button("ok"))
543{
544 m_xFileListLB->set_size_request(-1, m_xFileListLB->get_height_rows(10));
545
546 // Prepare the office for the following crash save step.
547 // E.g. hide all open windows so the user can't influence our
548 // operation .-)
550
551 m_xOkBtn->connect_clicked(LINK(this, SaveDialog, OKButtonHdl));
552
553 // fill listbox with current open documents
554
556
557 for (const TURLInfo& rInfo : rURLs)
558 {
559 m_xFileListLB->append("", rInfo.DisplayName, rInfo.StandardImageId);
560 }
561}
562
564{
565}
566
568{
569 // start crash-save with progress
570 std::unique_ptr<SaveProgressDialog> xProgress(new SaveProgressDialog(m_xDialog.get(), m_pCore));
571 short nResult = xProgress->run();
572 xProgress.reset();
573
574 // if "CANCEL" => return "CANCEL"
575 // if "OK" => "AUTOLUNCH" always !
576 if (nResult == DLG_RET_OK)
577 nResult = DLG_RET_OK_AUTOLUNCH;
578
579 m_xDialog->response(nResult);
580}
581
583 : GenericDialogController(pParent, "svx/ui/docrecoveryprogressdialog.ui", "DocRecoveryProgressDialog")
584 , m_pCore(pCore)
585 , m_xProgressBar(m_xBuilder->weld_progress_bar("progress"))
586{
587 m_xProgressBar->set_size_request(m_xProgressBar->get_approximate_digit_width() * 50, -1);
589}
590
592{
593 css::uno::Reference<css::lang::XComponent> xComp(m_xProgress, css::uno::UNO_QUERY);
594 if (xComp)
595 xComp->dispose();
596}
597
599{
601
605 short nRet = DialogController::run();
606 m_pCore->setUpdateListener(nullptr);
607 return nRet;
608}
609
611{
612}
613
615{
616 /* TODO
617
618 if m_pCore would have a member m_mCurrentItem, you could see,
619 who is current, who is next ... You can show this information
620 in progress report FixText
621 */
622}
623
625{
626 m_xDialog->response(DLG_RET_OK);
627}
628
630{
631 std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog(pParent,
632 VclMessageType::Question, VclButtonsType::YesNo, SvxResId(pRes)));
633 if (xQuery->run() == RET_YES)
634 return DLG_RET_OK;
635 else
636 return DLG_RET_CANCEL;
637}
638
640 : GenericDialogController(pParent, "svx/ui/docrecoveryrecoverdialog.ui", "DocRecoveryRecoverDialog")
641 , m_aTitleRecoveryInProgress(SvxResId(RID_SVXSTR_RECOVERY_INPROGRESS))
642 , m_aRecoveryOnlyFinish (SvxResId(RID_SVXSTR_RECOVERYONLY_FINISH))
643 , m_aRecoveryOnlyFinishDescr(SvxResId(RID_SVXSTR_RECOVERYONLY_FINISH_DESCR))
644 , m_pCore(pCore)
645 , m_eRecoveryState(RecoveryDialog::E_RECOVERY_PREPARED)
646 , m_bWaitForCore(false)
647 , m_bWasRecoveryStarted(false)
648 , m_aSuccessRecovStr(SvxResId(RID_SVXSTR_SUCCESSRECOV))
649 , m_aOrigDocRecovStr(SvxResId(RID_SVXSTR_ORIGDOCRECOV))
650 , m_aRecovFailedStr(SvxResId(RID_SVXSTR_RECOVFAILED))
651 , m_aRecovInProgrStr(SvxResId(RID_SVXSTR_RECOVINPROGR))
652 , m_aNotRecovYetStr(SvxResId(RID_SVXSTR_NOTRECOVYET))
653 , m_xDescrFT(m_xBuilder->weld_label("desc"))
654 , m_xProgressBar(m_xBuilder->weld_progress_bar("progress"))
655 , m_xFileListLB(m_xBuilder->weld_tree_view("filelist"))
656 , m_xNextBtn(m_xBuilder->weld_button("next"))
657 , m_xCancelBtn(m_xBuilder->weld_button("cancel"))
658{
659 const auto nWidth = m_xFileListLB->get_approximate_digit_width() * 70;
660 m_xFileListLB->set_size_request(nWidth, m_xFileListLB->get_height_rows(10));
661 m_xProgressBar->set_size_request(m_xProgressBar->get_approximate_digit_width() * 50, -1);
663
664 std::vector<int> aWidths
665 {
666 o3tl::narrowing<int>(m_xFileListLB->get_checkbox_column_width()),
667 o3tl::narrowing<int>(60 * nWidth / 100),
668 o3tl::narrowing<int>(m_xFileListLB->get_checkbox_column_width())
669 };
670 m_xFileListLB->set_column_fixed_widths(aWidths);
671
672 m_xNextBtn->set_sensitive(true);
673 m_xNextBtn->connect_clicked( LINK( this, RecoveryDialog, NextButtonHdl ) );
674 m_xCancelBtn->connect_clicked( LINK( this, RecoveryDialog, CancelButtonHdl ) );
675
676 // fill list box first time
677 TURLList& rURLList = m_pCore->getURLListAccess();
678 for (size_t i = 0, nCount = rURLList.size(); i < nCount; ++i)
679 {
680 const TURLInfo& rInfo = rURLList[i];
681 m_xFileListLB->append();
682 m_xFileListLB->set_id(i, weld::toId(&rInfo));
683 m_xFileListLB->set_image(i, rInfo.StandardImageId, 0);
684 m_xFileListLB->set_text(i, rInfo.DisplayName, 1);
685 m_xFileListLB->set_image(i, impl_getStatusImage(rInfo), 2);
686 m_xFileListLB->set_text(i, impl_getStatusString(rInfo), 3);
687 }
688
689 // mark first item
690 if (m_xFileListLB->n_children())
691 m_xFileListLB->set_cursor(0);
692}
693
695{
696 css::uno::Reference<css::lang::XComponent> xComp(m_xProgress, css::uno::UNO_QUERY);
697 if (xComp)
698 xComp->dispose();
699}
700
702{
703 ::SolarMutexGuard aSolarLock;
704
705 switch (m_eRecoveryState)
706 {
708 {
709 // user decided to start recovery ...
711 // do it asynchronous (to allow repaints)
712 // and wait for this asynchronous operation.
714 m_xNextBtn->set_sensitive(false);
715 m_xCancelBtn->set_sensitive(false);
719
720 m_bWaitForCore = true;
723
724 m_pCore->setUpdateListener(nullptr);
726 return execute();
727 }
728
730 {
731 // the core finished it's task.
732 // let the user decide the next step.
735 m_xNextBtn->set_sensitive(true);
736 m_xCancelBtn->set_sensitive(false);
737 return 0;
738 }
739
741 {
742 // All documents were recovered.
743 // User decided to step to the "next" wizard page.
744 // Do it ... but check first, if there exist some
745 // failed recovery documents. They must be saved to
746 // a user selected directory.
747 short nRet = DLG_RET_UNKNOWN;
748 BrokenRecoveryDialog aBrokenRecoveryDialog(m_xDialog.get(), m_pCore, !m_bWasRecoveryStarted);
749 OUString sSaveDir = aBrokenRecoveryDialog.getSaveDirURL(); // get the default dir
750 if (aBrokenRecoveryDialog.isExecutionNeeded())
751 {
752 nRet = aBrokenRecoveryDialog.run();
753 sSaveDir = aBrokenRecoveryDialog.getSaveDirURL();
754 }
755
756 switch(nRet)
757 {
758 // no broken temp files exists
759 // step to the next wizard page
760 case DLG_RET_UNKNOWN :
761 {
763 return DLG_RET_OK;
764 }
765
766 // user decided to save the broken temp files
767 // do and forget it
768 // step to the next wizard page
769 case DLG_RET_OK :
770 {
774 return DLG_RET_OK;
775 }
776
777 // user decided to ignore broken temp files.
778 // Ask it again ... may be this decision was wrong.
779 // Results:
780 // IGNORE => remove broken temp files
781 // => step to the next wizard page
782 // CANCEL => step back to the recovery page
783 case DLG_RET_CANCEL :
784 {
785 // TODO ask user ...
788 return DLG_RET_OK;
789 }
790 }
791
793 return DLG_RET_OK;
794 }
795
797 {
798 // "YES" => break recovery
799 // But there exist different states, where "cancel" can be called.
800 // Handle it different.
803 else
805 return execute();
806 }
807
810 {
811 // We have to check if there exists some temp. files.
812 // They should be saved to a user defined location.
813 // If no temp files exists or user decided to ignore it ...
814 // we have to remove all recovery/session data anyway!
815 short nRet = DLG_RET_UNKNOWN;
816 BrokenRecoveryDialog aBrokenRecoveryDialog(m_xDialog.get(), m_pCore, !m_bWasRecoveryStarted);
817 OUString sSaveDir = aBrokenRecoveryDialog.getSaveDirURL(); // get the default save location
818
819 // dialog itself checks if there is a need to copy files for this mode.
820 // It uses the information m_bWasRecoveryStarted doing so.
821 if (aBrokenRecoveryDialog.isExecutionNeeded())
822 {
823 nRet = aBrokenRecoveryDialog.run();
824 sSaveDir = aBrokenRecoveryDialog.getSaveDirURL();
825 }
826
827 // Possible states:
828 // a) nRet == DLG_RET_UNKNOWN
829 // dialog was not shown ...
830 // because there exists no temp file for copy.
831 // => remove all recovery data
832 // b) nRet == DLG_RET_OK
833 // dialog was shown ...
834 // user decided to save temp files
835 // => save all OR broken temp files (depends from the time, where cancel was called)
836 // => remove all recovery data
837 // c) nRet == DLG_RET_CANCEL
838 // dialog was shown ...
839 // user decided to ignore temp files
840 // => remove all recovery data
841 // => a)/c) are the same ... b) has one additional operation
842
843 // b)
844 if (nRet == DLG_RET_OK)
845 {
848 else
849 m_pCore->saveAllTempEntries(sSaveDir);
850 }
851
852 // a,b,c)
855 else
858
859 // THERE IS NO WAY BACK. see impl_askUserForWizardCancel()!
860 return DLG_RET_CANCEL;
861 }
862 }
863
864 // should never be reached .-)
865 OSL_FAIL("Should never be reached!");
866 return DLG_RET_OK;
867}
868
870{
871 int c = m_xFileListLB->n_children();
872 for (int i = 0; i < c; ++i)
873 {
874 TURLInfo* pInfo = weld::fromId<TURLInfo*>(m_xFileListLB->get_id(i));
875 if ( !pInfo )
876 continue;
877
878 m_xFileListLB->set_image(i, impl_getStatusImage(*pInfo), 2);
879 OUString sStatus = impl_getStatusString( *pInfo );
880 if (!sStatus.isEmpty())
881 m_xFileListLB->set_text(i, sStatus, 3);
882 }
883}
884
886{
887 int c = m_xFileListLB->n_children();
888 for (int i=0; i < c; ++i)
889 {
890 TURLInfo* pInfo = weld::fromId<TURLInfo*>(m_xFileListLB->get_id(i));
891 if (pInfo->ID != pItem->ID)
892 continue;
893
894 m_xFileListLB->set_cursor(i);
895 m_xFileListLB->scroll_to_row(i);
896 break;
897 }
898}
899
901{
902 m_bWaitForCore = false;
903}
904
906{
907 switch (m_eRecoveryState)
908 {
911 execute();
912 break;
914 m_eRecoveryState = RecoveryDialog::E_RECOVERY_DONE;
915 execute();
916 break;
917 }
918
919 if (m_eRecoveryState == RecoveryDialog::E_RECOVERY_HANDLED)
920 {
921 m_xDialog->response(DLG_RET_OK);
922 }
923}
924
926{
927 switch (m_eRecoveryState)
928 {
930 if (impl_askUserForWizardCancel(m_xDialog.get(), RID_SVXSTR_QUERY_EXIT_RECOVERY) != DLG_RET_CANCEL)
931 {
932 m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED;
933 execute();
934 }
935 break;
937 m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED;
938 execute();
939 break;
940 }
941
942 if (m_eRecoveryState == RecoveryDialog::E_RECOVERY_HANDLED)
943 {
944 m_xDialog->response(RET_CANCEL);
945 }
946}
947
948OUString RecoveryDialog::impl_getStatusString( const TURLInfo& rInfo ) const
949{
950 OUString sStatus;
951 switch ( rInfo.RecoveryState )
952 {
954 sStatus = m_aSuccessRecovStr;
955 break;
957 sStatus = m_aOrigDocRecovStr;
958 break;
959 case E_RECOVERY_FAILED :
960 sStatus = m_aRecovFailedStr;
961 break;
963 sStatus = m_aRecovInProgrStr;
964 break;
966 sStatus = m_aNotRecovYetStr;
967 break;
968 default:
969 break;
970 }
971 return sStatus;
972}
973
975{
976 OUString sStatus;
977 switch ( rInfo.RecoveryState )
978 {
980 sStatus = RID_SVXBMP_GREENCHECK;
981 break;
983 sStatus = RID_SVXBMP_YELLOWCHECK;
984 break;
985 case E_RECOVERY_FAILED :
986 sStatus = RID_SVXBMP_REDCROSS;
987 break;
988 default:
989 break;
990 }
991 return sStatus;
992}
993
995 RecoveryCore* pCore,
996 bool bBeforeRecovery)
997 : GenericDialogController(pParent, "svx/ui/docrecoverybrokendialog.ui", "DocRecoveryBrokenDialog")
998 , m_pCore(pCore)
999 , m_bBeforeRecovery(bBeforeRecovery)
1000 , m_bExecutionNeeded(false)
1001 , m_xFileListLB(m_xBuilder->weld_tree_view("filelist"))
1002 , m_xSaveDirED(m_xBuilder->weld_entry("savedir"))
1003 , m_xSaveDirBtn(m_xBuilder->weld_button("change"))
1004 , m_xOkBtn(m_xBuilder->weld_button("ok"))
1005 , m_xCancelBtn(m_xBuilder->weld_button("cancel"))
1006{
1007 m_xSaveDirBtn->connect_clicked( LINK( this, BrokenRecoveryDialog, SaveButtonHdl ) );
1008 m_xOkBtn->connect_clicked( LINK( this, BrokenRecoveryDialog, OkButtonHdl ) );
1009 m_xCancelBtn->connect_clicked( LINK( this, BrokenRecoveryDialog, CancelButtonHdl ) );
1010
1012 INetURLObject aObj( m_sSavePath );
1013 OUString sPath;
1014 osl::FileBase::getSystemPathFromFileURL(aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ), sPath);
1015 m_xSaveDirED->set_text(sPath);
1016
1017 impl_refresh();
1018}
1019
1021{
1022}
1023
1025{
1026 m_bExecutionNeeded = false;
1027 TURLList& rURLList = m_pCore->getURLListAccess();
1028 for (const TURLInfo& rInfo : rURLList)
1029 {
1031 {
1032 // "Cancel" before recovery ->
1033 // search for any temp files!
1034 if (rInfo.TempURL.isEmpty())
1035 continue;
1036 }
1037 else
1038 {
1039 // "Cancel" after recovery ->
1040 // search for broken temp files
1042 continue;
1043 }
1044
1045 m_bExecutionNeeded = true;
1046
1047 m_xFileListLB->append(weld::toId(&rInfo), rInfo.DisplayName, rInfo.StandardImageId);
1048 }
1049 m_sSavePath.clear();
1050 m_xOkBtn->grab_focus();
1051}
1052
1054{
1055 return m_bExecutionNeeded;
1056}
1057
1059{
1060 return m_sSavePath;
1061}
1062
1064{
1065 OUString sPhysicalPath = comphelper::string::strip(m_xSaveDirED->get_text(), ' ');
1066 OUString sURL;
1067 osl::FileBase::getFileURLFromSystemPath( sPhysicalPath, sURL );
1068 m_sSavePath = sURL;
1069 while (m_sSavePath.isEmpty())
1070 impl_askForSavePath();
1071
1072 m_xDialog->response(DLG_RET_OK);
1073}
1074
1076{
1077 m_xDialog->response(RET_CANCEL);
1078}
1079
1081{
1082 impl_askForSavePath();
1083}
1084
1086{
1087 css::uno::Reference< css::ui::dialogs::XFolderPicker2 > xFolderPicker =
1089
1090 INetURLObject aURL(m_sSavePath, INetProtocol::File);
1091 xFolderPicker->setDisplayDirectory(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE));
1092 short nRet = xFolderPicker->execute();
1093 if (nRet == css::ui::dialogs::ExecutableDialogResults::OK)
1094 {
1095 m_sSavePath = xFolderPicker->getDirectory();
1096 OUString sPath;
1097 osl::FileBase::getSystemPathFromFileURL(m_sSavePath, sPath);
1098 m_xSaveDirED->set_text(sPath);
1099 }
1100}
1101
1102}
1103
1104/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::rtl::Reference< comphelper::OPropertyChangeMultiplexer > m_pListener
Reference< XComponentContext > m_xContext
Reference< XExecutableDialog > m_xDialog
AnyEventRef aEvent
static void Yield()
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
static bool IsQuit()
OUString getName(sal_Int32 nIndex=LAST_SEGMENT, bool bIgnoreFinalSlash=true, DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
static SVT_DLLPUBLIC OUString GetFileImageId(const INetURLObject &rURL)
const OUString & GetWorkPath() const
TValueType getUnpackedValueOrDefault(const OUString &sKey, const TValueType &aDefault) const
const OUString & getSaveDirURL() const
TODO.
BrokenRecoveryDialog(weld::Window *pParent, RecoveryCore *pCore, bool bBeforeRecovery)
TODO.
std::unique_ptr< weld::Button > m_xSaveDirBtn
std::unique_ptr< weld::Button > m_xCancelBtn
std::unique_ptr< weld::Entry > m_xSaveDirED
std::unique_ptr< weld::Button > m_xOkBtn
std::unique_ptr< weld::TreeView > m_xFileListLB
virtual void stepNext(TURLInfo *pItem)=0
PluginProgress(weld::ProgressBar *pProgressBar)
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
virtual void SAL_CALL setValue(sal_Int32 nValue) override
virtual void SAL_CALL setText(const OUString &sText) override
virtual void SAL_CALL start(const OUString &sText, sal_Int32 nRange) override
virtual void SAL_CALL reset() override
weld::ProgressBar * m_pProgressBar
virtual void SAL_CALL dispose() override
virtual ~PluginProgress() override
virtual void SAL_CALL end() override
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
IRecoveryUpdateListener * m_pListener
TODO.
css::uno::Reference< css::task::XStatusIndicator > m_xProgress
TODO.
TURLList & getURLListAccess()
TODO.
Definition: docrecovery.cxx:71
css::uno::Reference< css::uno::XComponentContext > m_xContext
TODO.
virtual void SAL_CALL disposing(const css::lang::EventObject &aEvent) override
void saveBrokenTempEntries(const OUString &sSaveDir)
Definition: docrecovery.cxx:94
RecoveryCore(const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool bUsedForSaving)
TODO.
Definition: docrecovery.cxx:49
virtual ~RecoveryCore() override
TODO.
Definition: docrecovery.cxx:59
virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent &aEvent) override
void setUpdateListener(IRecoveryUpdateListener *pListener)
TODO.
void impl_stopListening()
stop listening on the internal EmergencySave/AutoRecovery core.
static ERecoveryState mapDocState2RecoverState(EDocStates eDocState)
TODO.
void impl_startListening()
starts listening on the internal EmergencySave/AutoRecovery core.
const css::uno::Reference< css::uno::XComponentContext > & getComponentContext() const
TODO.
Definition: docrecovery.cxx:65
bool m_bListenForSaving
knows the reason, why we listen on our internal m_xRealCore member.
css::util::URL impl_getParsedURL(const OUString &sURL)
TODO.
void setProgressHandler(const css::uno::Reference< css::task::XStatusIndicator > &xProgress)
TODO.
void saveAllTempEntries(const OUString &sSaveDir)
static bool isBrokenTempEntry(const TURLInfo &rInfo)
TODO.
Definition: docrecovery.cxx:77
css::uno::Reference< css::frame::XDispatch > m_xRealCore
TODO.
std::unique_ptr< weld::Button > m_xCancelBtn
std::unique_ptr< weld::TreeView > m_xFileListLB
virtual void stepNext(TURLInfo *pItem) override
virtual ~RecoveryDialog() override
RecoveryDialog(weld::Window *pParent, RecoveryCore *pCore)
TODO.
OUString impl_getStatusString(const TURLInfo &rInfo) const
virtual void updateItems() override
std::unique_ptr< weld::Button > m_xNextBtn
static OUString impl_getStatusImage(const TURLInfo &rInfo)
std::unique_ptr< weld::ProgressBar > m_xProgressBar
css::uno::Reference< css::task::XStatusIndicator > m_xProgress
std::unique_ptr< weld::Label > m_xDescrFT
virtual void end() override
SaveDialog(weld::Window *pParent, RecoveryCore *pCore)
create all child controls of this dialog.
std::unique_ptr< weld::Button > m_xOkBtn
virtual ~SaveDialog() override
std::unique_ptr< weld::TreeView > m_xFileListLB
virtual void updateItems() override
css::uno::Reference< css::task::XStatusIndicator > m_xProgress
std::unique_ptr< weld::ProgressBar > m_xProgressBar
SaveProgressDialog(weld::Window *pParent, RecoveryCore *pCore)
create all child controls of this dialog.
virtual short run() override
start the emergency save operation.
virtual void stepNext(TURLInfo *pItem) override
virtual short run()
std::shared_ptr< weld::Dialog > m_xDialog
virtual void set_text(const OUString &rText)=0
virtual void set_percentage(int value)=0
int nCount
OUString SvxResId(TranslateId aId)
Definition: dialmgr.cxx:24
URL aURL
constexpr OUStringLiteral RECOVERY_CMD_DO_PREPARE_EMERGENCY_SAVE
Definition: docrecovery.hxx:40
constexpr OUStringLiteral RECOVERY_CMD_DO_EMERGENCY_SAVE
Definition: docrecovery.hxx:41
constexpr OUStringLiteral STATEPROP_ORGURL
Definition: docrecovery.hxx:53
#define DLG_RET_OK
Definition: docrecovery.hxx:65
constexpr OUStringLiteral STATEPROP_TEMPURL
Definition: docrecovery.hxx:54
constexpr OUStringLiteral STATEPROP_TITLE
Definition: docrecovery.hxx:57
constexpr OUStringLiteral RECOVERY_CMD_DO_ENTRY_BACKUP
Definition: docrecovery.hxx:43
constexpr OUStringLiteral STATEPROP_MODULE
Definition: docrecovery.hxx:58
constexpr OUStringLiteral STATEPROP_STATE
Definition: docrecovery.hxx:52
constexpr OUStringLiteral RECOVERY_CMD_DO_RECOVERY
Definition: docrecovery.hxx:42
constexpr OUStringLiteral STATEPROP_ID
Definition: docrecovery.hxx:51
constexpr OUStringLiteral RECOVERY_CMD_DO_ENTRY_CLEANUP
Definition: docrecovery.hxx:44
#define DLG_RET_UNKNOWN
Definition: docrecovery.hxx:64
#define DLG_RET_OK_AUTOLUNCH
Definition: docrecovery.hxx:67
constexpr OUStringLiteral PROP_DISPATCHASYNCHRON
Definition: docrecovery.hxx:47
#define DLG_RET_CANCEL
Definition: docrecovery.hxx:66
#define RECOVERY_OPERATIONSTATE_UPDATE
Definition: docrecovery.hxx:62
#define RECOVERY_OPERATIONSTATE_START
Definition: docrecovery.hxx:60
constexpr OUStringLiteral PROP_SAVEPATH
Definition: docrecovery.hxx:48
constexpr OUStringLiteral PROP_STATUSINDICATOR
Definition: docrecovery.hxx:46
constexpr OUStringLiteral STATEPROP_TEMPLATEURL
Definition: docrecovery.hxx:56
constexpr OUStringLiteral STATEPROP_FACTORYURL
Definition: docrecovery.hxx:55
constexpr OUStringLiteral PROP_ENTRYID
Definition: docrecovery.hxx:49
#define RECOVERY_OPERATIONSTATE_STOP
Definition: docrecovery.hxx:61
EDocStates
Definition: docrecovery.hxx:71
@ Incomplete
the Auto/Emergency saved document is not really up-to-date (some changes can be missing)
@ Succeeded
the Auto/Emergency saved document was processed successfully
@ TryLoadBackup
an action was started (saving/loading) ... Can be interesting later if the process may be was interru...
@ Damaged
the Auto/Emergency saved document isn't usable any longer
Mutex aLock
sal_Int16 nValue
Definition: fmsrccfg.cxx:81
OString strip(const OString &rIn, char c)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
int i
css::uno::Reference< css::ui::dialogs::XFolderPicker2 > createFolderPicker(const css::uno::Reference< css::uno::XComponentContext > &rContext, weld::Window *pPreferredParent)
::std::vector< TURLInfo > TURLList
static short impl_askUserForWizardCancel(weld::Widget *pParent, TranslateId pRes)
IMPL_LINK_NOARG(SaveDialog, OKButtonHdl, weld::Button &, void)
OUString toId(const void *pValue)
OUString TemplateURL
may be the document base on a template file !?
ERecoveryState RecoveryState
ui representation for DocState!
OUString FactoryURL
a may be existing factory URL (e.g. for untitled documents)
OUString DisplayName
the pure file name, without path, disc etcpp.
OUString TempURL
the full qualified URL of the temp. file (if it's exists)
EDocStates DocState
state info as e.g. VALID, CORRUPTED, NON EXISTING ...
OUString StandardImageId
standard icon
OUString OrgURL
the full qualified document URL
OUString Module
the application module, where this document was loaded
sal_Int32 ID
unique ID, which is specified by the underlying autorecovery core!
RET_CANCEL
RET_YES