summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeiko Tietze <tietze.heiko@gmail.com>2022-07-06 15:11:28 +0200
committerCaolán McNamara <caolanm@redhat.com>2022-08-05 16:25:46 +0200
commita9c8ac0605fd1d19e1d79b54804b610a64a8a056 (patch)
tree41e15dd42567bc1e2a7292659e0ffbcaf8978553
parent057c60192aa34ae42f9f8abc2cb0ec93caa79130 (diff)
Resolves tdf#114508: Individual selection in recovery dialog
Based on work by Danie Truter at I397119a6e50c256e87e3a484a6c17a252f191981 Change-Id: I75fd321cbfeb7a92bd14e94b0c1ae0bb25be73cd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136845 Tested-by: Jenkins Tested-by: Heiko Tietze <heiko.tietze@documentfoundation.org> Reviewed-by: Heiko Tietze <heiko.tietze@documentfoundation.org> Tested-by: Caolán McNamara <caolanm@redhat.com> Reviewed-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--include/svx/strings.hrc1
-rw-r--r--svx/source/dialog/docrecovery.cxx140
-rw-r--r--svx/source/inc/docrecovery.hxx12
-rw-r--r--svx/uiconfig/ui/docrecoveryrecoverdialog.ui83
4 files changed, 185 insertions, 51 deletions
diff --git a/include/svx/strings.hrc b/include/svx/strings.hrc
index f800d8365cf5..f46663ccf669 100644
--- a/include/svx/strings.hrc
+++ b/include/svx/strings.hrc
@@ -1020,6 +1020,7 @@
#define RID_SVXSTR_RECOVFAILED NC_("RID_SVXSTR_RECOVFAILED", "Recovery failed")
#define RID_SVXSTR_RECOVINPROGR NC_("RID_SVXSTR_RECOVINPROGR", "Recovery in progress")
#define RID_SVXSTR_NOTRECOVYET NC_("RID_SVXSTR_NOTRECOVYET", "Not recovered yet")
+#define RID_SVXSTR_WILLDISCARD NC_("RID_SVXSTR_WILLDISCARD", "Will be discarded")
#define RID_SVXSTR_RECOVERY_INPROGRESS NC_("RID_SVXSTR_RECOVERY_INPROGRESS", "%PRODUCTNAME %PRODUCTVERSION has begun recovering your documents. Depending on the size of the documents this process can take some time.")
#define RID_SVXSTR_RECOVERYONLY_FINISH_DESCR NC_("RID_SVXSTR_RECOVERYONLY_FINISH_DESCR", "Recovery of your documents was finished. Click 'Finish' to see your documents.")
#define RID_SVXSTR_RECOVERYONLY_FINISH NC_("RID_SVXSTR_RECOVERYONLY_FINISH", "~Finish")
diff --git a/svx/source/dialog/docrecovery.cxx b/svx/source/dialog/docrecovery.cxx
index 61a2fedb4f8a..6675a05c64ea 100644
--- a/svx/source/dialog/docrecovery.cxx
+++ b/svx/source/dialog/docrecovery.cxx
@@ -47,6 +47,11 @@ namespace svx::DocRecovery
using namespace ::osl;
+#define COLUMN_STANDARDIMAGE -1
+#define COLUMN_DISPLAYNAME 0
+#define COLUMN_STATUSIMAGE 1
+#define COLUMN_STATUSTEXT 2
+
RecoveryCore::RecoveryCore(css::uno::Reference< css::uno::XComponentContext > xContext,
bool bUsedForSaving)
: m_xContext (std::move( xContext ))
@@ -190,6 +195,33 @@ void RecoveryCore::forgetBrokenTempEntries()
}
}
+// should only be called with valid m_xRealCore
+void RecoveryCore::forgetAllRecoveryEntriesMarkedForDiscard()
+{
+ assert(m_xRealCore);
+
+ // potential to move in a separate function
+ css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
+ css::uno::Sequence<css::beans::PropertyValue> lRemoveArgs(2);
+ auto plRemoveArgs = lRemoveArgs.getArray();
+ plRemoveArgs[0].Name = PROP_DISPATCHASYNCHRON;
+ plRemoveArgs[0].Value <<= false;
+ plRemoveArgs[1].Name = PROP_ENTRYID;
+
+ // work on a copied list only ...
+ // Reason: We will get notifications from the core for every
+ // changed or removed element. And that will change our m_lURLs list.
+ // That's not a good idea, if we use a stl iterator inbetween .-)
+ TURLList lURLs = m_lURLs;
+ for (const TURLInfo& rInfo : lURLs)
+ {
+ if (!rInfo.ShouldDiscard)
+ continue;
+
+ plRemoveArgs[1].Value <<= rInfo.ID;
+ m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
+ }
+}
void RecoveryCore::forgetAllRecoveryEntries()
{
@@ -293,6 +325,8 @@ void RecoveryCore::doRecovery()
if (!m_xRealCore.is())
return;
+ forgetAllRecoveryEntriesMarkedForDiscard();
+
css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_RECOVERY);
css::uno::Sequence< css::beans::PropertyValue > lArgs{
@@ -646,29 +680,31 @@ RecoveryDialog::RecoveryDialog(weld::Window* pParent, RecoveryCore* pCore)
, m_eRecoveryState(RecoveryDialog::E_RECOVERY_PREPARED)
, m_bWaitForCore(false)
, m_bWasRecoveryStarted(false)
+// , m_aColumnOffset(0)
+ , m_aToggleCount(0)
, m_aSuccessRecovStr(SvxResId(RID_SVXSTR_SUCCESSRECOV))
, m_aOrigDocRecovStr(SvxResId(RID_SVXSTR_ORIGDOCRECOV))
, m_aRecovFailedStr(SvxResId(RID_SVXSTR_RECOVFAILED))
, m_aRecovInProgrStr(SvxResId(RID_SVXSTR_RECOVINPROGR))
, m_aNotRecovYetStr(SvxResId(RID_SVXSTR_NOTRECOVYET))
+ , m_aWillBeDiscStr(SvxResId(RID_SVXSTR_WILLDISCARD))
, m_xDescrFT(m_xBuilder->weld_label("desc"))
, m_xProgressBar(m_xBuilder->weld_progress_bar("progress"))
, m_xFileListLB(m_xBuilder->weld_tree_view("filelist"))
, m_xNextBtn(m_xBuilder->weld_button("next"))
, m_xCancelBtn(m_xBuilder->weld_button("cancel"))
{
- const auto nWidth = m_xFileListLB->get_approximate_digit_width() * 70;
+ const auto nWidth = m_xFileListLB->get_approximate_digit_width() * 80;
m_xFileListLB->set_size_request(nWidth, m_xFileListLB->get_height_rows(10));
m_xProgressBar->set_size_request(m_xProgressBar->get_approximate_digit_width() * 50, -1);
m_xProgress = new PluginProgress(m_xProgressBar.get());
- std::vector<int> aWidths
- {
- o3tl::narrowing<int>(m_xFileListLB->get_checkbox_column_width()),
- o3tl::narrowing<int>(60 * nWidth / 100),
- o3tl::narrowing<int>(m_xFileListLB->get_checkbox_column_width())
- };
+ std::vector<int> aWidths;
+ aWidths.push_back(60 * nWidth / 100);
+ aWidths.push_back(5 * nWidth / 100);
m_xFileListLB->set_column_fixed_widths(aWidths);
+ m_xFileListLB->enable_toggle_buttons(weld::ColumnToggleType::Check);
+ m_xFileListLB->connect_toggled( LINK(this, RecoveryDialog, ToggleRowHdl) );
m_xNextBtn->set_sensitive(true);
m_xNextBtn->connect_clicked( LINK( this, RecoveryDialog, NextButtonHdl ) );
@@ -680,11 +716,13 @@ RecoveryDialog::RecoveryDialog(weld::Window* pParent, RecoveryCore* pCore)
{
const TURLInfo& rInfo = rURLList[i];
m_xFileListLB->append();
+ m_xFileListLB->set_toggle(i, TRISTATE_TRUE);
m_xFileListLB->set_id(i, weld::toId(&rInfo));
- m_xFileListLB->set_image(i, rInfo.StandardImageId, 0);
- m_xFileListLB->set_text(i, rInfo.DisplayName, 1);
- m_xFileListLB->set_image(i, impl_getStatusImage(rInfo), 2);
- m_xFileListLB->set_text(i, impl_getStatusString(rInfo), 3);
+ m_xFileListLB->set_image(i, rInfo.StandardImageId, COLUMN_STANDARDIMAGE);
+ m_xFileListLB->set_text(i, rInfo.DisplayName, COLUMN_DISPLAYNAME);
+ m_xFileListLB->set_image(i, impl_getStatusImage(rInfo), COLUMN_STATUSIMAGE);
+ m_xFileListLB->set_text(i, impl_getStatusString(rInfo), COLUMN_STATUSTEXT);
+ m_aToggleCount++;
}
// mark first item
@@ -876,10 +914,10 @@ void RecoveryDialog::updateItems()
if ( !pInfo )
continue;
- m_xFileListLB->set_image(i, impl_getStatusImage(*pInfo), 2);
+ m_xFileListLB->set_image(i, impl_getStatusImage(*pInfo), COLUMN_STATUSIMAGE);
OUString sStatus = impl_getStatusString( *pInfo );
if (!sStatus.isEmpty())
- m_xFileListLB->set_text(i, sStatus, 3);
+ m_xFileListLB->set_text(i, sStatus, COLUMN_STATUSTEXT);
}
}
@@ -946,6 +984,52 @@ IMPL_LINK_NOARG(RecoveryDialog, CancelButtonHdl, weld::Button&, void)
}
}
+IMPL_LINK_NOARG(RecoveryDialog, ToggleRowHdl, const weld::TreeView::iter_col&, void)
+{
+ int aIndex = m_xFileListLB->get_selected_index();
+ TriState eState = m_xFileListLB->get_toggle(aIndex);
+
+ if (m_bWasRecoveryStarted)
+ {
+ switch (eState)
+ {
+ case TRISTATE_FALSE:
+ eState = TRISTATE_TRUE;
+ break;
+ case TRISTATE_TRUE:
+ eState = TRISTATE_FALSE;
+ break;
+ default:
+ // should never happen
+ assert(false);
+ break;
+ }
+
+ // revert toggle
+ m_xFileListLB->set_toggle(aIndex, eState);
+ }
+ else
+ {
+ impl_updateItemDescription(aIndex, eState);
+
+ switch (eState)
+ {
+ case TRISTATE_FALSE:
+ m_aToggleCount--;
+ break;
+ case TRISTATE_TRUE:
+ m_aToggleCount++;
+ break;
+ default:
+ // should never happen
+ assert(false);
+ break;
+ }
+
+ m_xNextBtn->set_sensitive(m_aToggleCount != 0);
+ }
+}
+
OUString RecoveryDialog::impl_getStatusString( const TURLInfo& rInfo ) const
{
OUString sStatus;
@@ -966,6 +1050,9 @@ OUString RecoveryDialog::impl_getStatusString( const TURLInfo& rInfo ) const
case E_NOT_RECOVERED_YET :
sStatus = m_aNotRecovYetStr;
break;
+ case E_WILL_BE_DISCARDED:
+ sStatus = m_aWillBeDiscStr;
+ break;
default:
break;
}
@@ -992,6 +1079,33 @@ OUString RecoveryDialog::impl_getStatusImage( const TURLInfo& rInfo )
return sStatus;
}
+void RecoveryDialog::impl_updateItemDescription(int row, const TriState& rState)
+{
+ TURLInfo* pInfo = reinterpret_cast<TURLInfo*>(m_xFileListLB->get_id(row).toInt64());
+ if (!pInfo)
+ return;
+
+ switch (rState)
+ {
+ case TRISTATE_FALSE:
+ pInfo->RecoveryState = ERecoveryState::E_WILL_BE_DISCARDED;
+ pInfo->ShouldDiscard = true;
+ break;
+ case TRISTATE_TRUE:
+ pInfo->RecoveryState = ERecoveryState::E_NOT_RECOVERED_YET;
+ pInfo->ShouldDiscard = false;
+ break;
+ default:
+ // should never happen
+ assert(false);
+ break;
+ }
+
+ OUString sStatus = impl_getStatusString(*pInfo);
+ if (!sStatus.isEmpty())
+ m_xFileListLB->set_text(row, sStatus, COLUMN_STATUSTEXT);
+}
+
BrokenRecoveryDialog::BrokenRecoveryDialog(weld::Window* pParent,
RecoveryCore* pCore,
bool bBeforeRecovery)
diff --git a/svx/source/inc/docrecovery.hxx b/svx/source/inc/docrecovery.hxx
index df90e5354f56..d7442d2c7ab1 100644
--- a/svx/source/inc/docrecovery.hxx
+++ b/svx/source/inc/docrecovery.hxx
@@ -101,7 +101,8 @@ enum ERecoveryState
E_ORIGINAL_DOCUMENT_RECOVERED,
E_RECOVERY_FAILED,
E_RECOVERY_IS_IN_PROGRESS,
- E_NOT_RECOVERED_YET
+ E_NOT_RECOVERED_YET,
+ E_WILL_BE_DISCARDED,
};
@@ -139,12 +140,16 @@ struct TURLInfo
/// standard icon
OUString StandardImageId;
+ /// user choice to discard
+ bool ShouldDiscard;
+
public:
TURLInfo()
: ID (-1 )
, DocState (EDocStates::Unknown)
, RecoveryState(E_NOT_RECOVERED_YET)
+ , ShouldDiscard(false)
{}
};
@@ -233,6 +238,7 @@ class RecoveryCore final : public ::cppu::WeakImplHelper< css::frame::XStatusLis
void forgetBrokenTempEntries();
void forgetAllRecoveryEntries();
void forgetBrokenRecoveryEntries();
+ void forgetAllRecoveryEntriesMarkedForDiscard();
/** @short TODO */
@@ -404,12 +410,14 @@ class RecoveryDialog final : public weld::GenericDialogController
sal_Int32 m_eRecoveryState;
bool m_bWaitForCore;
bool m_bWasRecoveryStarted;
+ int m_aToggleCount;
OUString m_aSuccessRecovStr;
OUString m_aOrigDocRecovStr;
OUString m_aRecovFailedStr;
OUString m_aRecovInProgrStr;
OUString m_aNotRecovYetStr;
+ OUString m_aWillBeDiscStr;
std::unique_ptr<weld::Label> m_xDescrFT;
std::unique_ptr<weld::ProgressBar> m_xProgressBar;
@@ -436,9 +444,11 @@ class RecoveryDialog final : public weld::GenericDialogController
private:
DECL_LINK(NextButtonHdl, weld::Button&, void);
DECL_LINK(CancelButtonHdl, weld::Button&, void);
+ DECL_LINK(ToggleRowHdl, const weld::TreeView::iter_col&, void);
OUString impl_getStatusString( const TURLInfo& rInfo ) const;
static OUString impl_getStatusImage( const TURLInfo& rInfo );
+ void impl_updateItemDescription(int row, const TriState& rState);
};
diff --git a/svx/uiconfig/ui/docrecoveryrecoverdialog.ui b/svx/uiconfig/ui/docrecoveryrecoverdialog.ui
index a7dcc775269d..70a1ccbb7550 100644
--- a/svx/uiconfig/ui/docrecoveryrecoverdialog.ui
+++ b/svx/uiconfig/ui/docrecoveryrecoverdialog.ui
@@ -4,22 +4,29 @@
<requires lib="gtk+" version="3.20"/>
<object class="GtkTreeStore" id="liststore1">
<columns>
- <!-- column-name image -->
+ <!-- column-name checkbox -->
+ <column type="gboolean"/>
+ <!-- column-name standardimage -->
<column type="GdkPixbuf"/>
- <!-- column-name text -->
+ <!-- column-name displayname -->
<column type="gchararray"/>
- <!-- column-name image2 -->
+ <!-- column-name statustimage -->
<column type="GdkPixbuf"/>
- <!-- column-name text1 -->
+ <!-- column-name statustext -->
<column type="gchararray"/>
<!-- column-name id -->
<column type="gchararray"/>
+ <!-- column-name chkVis -->
+ <column type="gboolean"/>
+ <!-- column-name chkTri -->
+ <column type="gboolean"/>
</columns>
</object>
<object class="GtkDialog" id="DocRecoveryRecoverDialog">
<property name="can-focus">False</property>
<property name="border-width">6</property>
<property name="title" translatable="yes" context="docrecoveryrecoverdialog|DocRecoveryRecoverDialog">%PRODUCTNAME %PRODUCTVERSION Document Recovery</property>
+ <property name="resizable">False</property>
<property name="modal">True</property>
<property name="default-width">0</property>
<property name="default-height">0</property>
@@ -35,7 +42,7 @@
<property name="layout-style">end</property>
<child>
<object class="GtkButton" id="cancel">
- <property name="label" translatable="yes" context="docrecoveryrecoverdialog|cancel">_Discard</property>
+ <property name="label" translatable="yes" context="docrecoveryrecoverdialog|cancel">_Discard All</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="can-default">True</property>
@@ -50,7 +57,7 @@
</child>
<child>
<object class="GtkButton" id="next">
- <property name="label" translatable="yes" context="docrecoveryrecoverdialog|next">_Start</property>
+ <property name="label" translatable="yes" context="docrecoveryrecoverdialog|next">_Recover Selected</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="can-default">True</property>
@@ -69,11 +76,11 @@
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack-type">end</property>
- <property name="position">0</property>
+ <property name="position">2</property>
</packing>
</child>
<child>
- <!-- n-columns=1 n-rows=4 -->
+ <!-- n-columns=1 n-rows=3 -->
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can-focus">False</property>
@@ -84,7 +91,7 @@
<object class="GtkLabel" id="desc">
<property name="visible">True</property>
<property name="can-focus">False</property>
- <property name="label" translatable="yes" context="docrecoveryrecoverdialog|desc">%PRODUCTNAME will attempt to recover the state of the files you were working on before it crashed. Click 'Start' to begin the process, or click 'Discard' to cancel the recovery.</property>
+ <property name="label" translatable="yes" context="docrecoveryrecoverdialog|desc">%PRODUCTNAME will attempt to recover the state of the files you were working on before it crashed. Click 'Recover Selected' to begin the process, or click 'Discard' to cancel the recovery.</property>
<property name="wrap">True</property>
<property name="width-chars">70</property>
<property name="max-width-chars">70</property>
@@ -96,17 +103,6 @@
</packing>
</child>
<child>
- <object class="GtkProgressBar" id="progress">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="hexpand">True</property>
- </object>
- <packing>
- <property name="left-attach">0</property>
- <property name="top-attach">1</property>
- </packing>
- </child>
- <child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can-focus">False</property>
@@ -117,7 +113,7 @@
</object>
<packing>
<property name="left-attach">0</property>
- <property name="top-attach">2</property>
+ <property name="top-attach">1</property>
</packing>
</child>
<child>
@@ -142,43 +138,45 @@
<object class="GtkTreeSelection" id="treeview-selection2"/>
</child>
<child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn0">
+ <object class="GtkTreeViewColumn" id="colRecover">
+ <property name="title" translatable="yes" context="docrecoveryrecoverdialog|recoverft">Recover Document</property>
<child>
- <object class="GtkCellRendererPixbuf" id="cellrenderertext9"/>
+ <object class="GtkCellRendererToggle" id="cellrenderertoggle"/>
<attributes>
- <attribute name="pixbuf">0</attribute>
+ <attribute name="active">0</attribute>
</attributes>
</child>
- </object>
- </child>
- <child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn1">
- <property name="title" translatable="yes" context="docrecoveryrecoverdialog|nameft">Document Name</property>
<child>
- <object class="GtkCellRendererText" id="cellrenderertext2"/>
+ <object class="GtkCellRendererPixbuf" id="cellrendererstandardimage"/>
<attributes>
- <attribute name="text">1</attribute>
+ <attribute name="pixbuf">1</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText" id="cellrendererdisplayname"/>
+ <attributes>
+ <attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <object class="GtkTreeViewColumn" id="colStatusImage">
<child>
- <object class="GtkCellRendererPixbuf" id="cellrenderertext4"/>
+ <object class="GtkCellRendererPixbuf" id="cellrendererstatusimage"/>
<attributes>
- <attribute name="pixbuf">2</attribute>
+ <attribute name="pixbuf">3</attribute>
</attributes>
</child>
</object>
</child>
<child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+ <object class="GtkTreeViewColumn" id="colStatusText">
<property name="title" translatable="yes" context="docrecoveryrecoverdialog|statusft">Status</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext3"/>
<attributes>
- <attribute name="text">3</attribute>
+ <attribute name="text">4</attribute>
</attributes>
</child>
</object>
@@ -188,13 +186,24 @@
</object>
<packing>
<property name="left-attach">0</property>
- <property name="top-attach">3</property>
+ <property name="top-attach">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkProgressBar" id="progress">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>