diff options
author | Pierre-Eric Pelloux-Prayer <pierre-eric@lanedo.com> | 2013-10-16 10:07:08 +0200 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2013-10-29 13:50:33 +0000 |
commit | eb42610c43b1011cde0af8b03d20ec70e4e789b5 (patch) | |
tree | 95aad299b12741b2c8f911ff7b9d642086361b65 /sw | |
parent | 38b8e742872b2cbdba93f4d1b84c8f09b5ab38ff (diff) |
sw: clone InputField dialog on input-field removal
Setup a listener on RES_FIELD_DELETED event, and cancel dialog if
a field is deleted. Add Cancellable capability to Input dialog too.
Fixes a crasher that occurs when fields are removed (e.g: by an
extension) while the InputField dialog is running.
Change-Id: I9e132a109cba3127b934a3baecbf445a2bde1377
Reviewed-on: https://gerrit.libreoffice.org/6261
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/inc/swabstdlg.hxx | 3 | ||||
-rw-r--r-- | sw/source/ui/dialog/swdlgfact.cxx | 5 | ||||
-rw-r--r-- | sw/source/ui/dialog/swdlgfact.hxx | 1 | ||||
-rw-r--r-- | sw/source/ui/wrtsh/wrtsh2.cxx | 38 |
4 files changed, 44 insertions, 3 deletions
diff --git a/sw/inc/swabstdlg.hxx b/sw/inc/swabstdlg.hxx index 32d1d37f0b15..e1f5d7c60aea 100644 --- a/sw/inc/swabstdlg.hxx +++ b/sw/inc/swabstdlg.hxx @@ -99,12 +99,13 @@ public: virtual OUString GetCurrShortName() const = 0; }; -class AbstractFldInputDlg : public VclAbstractDialog +class AbstractFldInputDlg : public VclAbstractTerminatedDialog { public: //from class SalFrame virtual void SetWindowState( const OString & rStr ) = 0; virtual OString GetWindowState( sal_uLong nMask = WINDOWSTATE_MASK_ALL ) const = 0; + virtual void EndDialog(long ) = 0; }; class AbstractInsFootNoteDlg : public VclAbstractDialog diff --git a/sw/source/ui/dialog/swdlgfact.cxx b/sw/source/ui/dialog/swdlgfact.cxx index bfd44dddbf40..e337589c65f1 100644 --- a/sw/source/ui/dialog/swdlgfact.cxx +++ b/sw/source/ui/dialog/swdlgfact.cxx @@ -414,6 +414,11 @@ OString AbstractFldInputDlg_Impl::GetWindowState( sal_uLong nMask ) const return pDlg->GetWindowState( nMask ); } +void AbstractFldInputDlg_Impl::EndDialog(long n) +{ + pDlg->EndDialog(n); +} + OUString AbstractInsFootNoteDlg_Impl::GetFontName() { return pDlg->GetFontName(); diff --git a/sw/source/ui/dialog/swdlgfact.hxx b/sw/source/ui/dialog/swdlgfact.hxx index fc80b86a4af8..09d59637ffcf 100644 --- a/sw/source/ui/dialog/swdlgfact.hxx +++ b/sw/source/ui/dialog/swdlgfact.hxx @@ -245,6 +245,7 @@ class AbstractFldInputDlg_Impl : public AbstractFldInputDlg //from class SalFrame virtual void SetWindowState( const OString & rStr ) ; virtual OString GetWindowState( sal_uLong nMask = WINDOWSTATE_MASK_ALL ) const ; + virtual void EndDialog(long); }; class SwInsFootNoteDlg; diff --git a/sw/source/ui/wrtsh/wrtsh2.cxx b/sw/source/ui/wrtsh/wrtsh2.cxx index 0e034e8174df..56046475210d 100644 --- a/sw/source/ui/wrtsh/wrtsh2.cxx +++ b/sw/source/ui/wrtsh/wrtsh2.cxx @@ -124,8 +124,11 @@ void SwWrtShell::UpdateInputFlds( SwInputFieldList* pLst, sal_Bool bOnlyInSel ) else bCancel = StartInputFldDlg( pField, sal_True, 0, &aDlgPos); - // Otherwise update error at multi-selection: - pTmp->GetField( i )->GetTyp()->UpdateFlds(); + if (!bCancel) + { + // Otherwise update error at multi-selection: + pTmp->GetField( i )->GetTyp()->UpdateFlds(); + } } pTmp->PopCrsr(); } @@ -134,6 +137,28 @@ void SwWrtShell::UpdateInputFlds( SwInputFieldList* pLst, sal_Bool bOnlyInSel ) delete pTmp; } +// Listener class: will close InputField dialog if input field(s) +// is(are) deleted (for instance, by an extension) after the dialog shows up. +// Otherwise, the for loop in SwWrtShell::UpdateInputFlds will crash when doing: +// 'pTmp->GetField( i )->GetTyp()->UpdateFlds();' +// on a deleted field. +class FieldDeletionModify : public SwModify +{ + public: + FieldDeletionModify(AbstractFldInputDlg* pInputFieldDlg) : mpInputFieldDlg(pInputFieldDlg) {} + + void Modify( const SfxPoolItem* pOld, const SfxPoolItem *) + { + // Input fields have been deleted: better to close the dialog + if (pOld->Which() == RES_FIELD_DELETED) + { + mpInputFieldDlg->EndDialog(RET_CANCEL); + } + } + private: + AbstractFldInputDlg* mpInputFieldDlg; +}; + // Start input dialog for a specific field sal_Bool SwWrtShell::StartInputFldDlg( SwField* pFld, sal_Bool bNextButton, @@ -146,7 +171,16 @@ sal_Bool SwWrtShell::StartInputFldDlg( SwField* pFld, sal_Bool bNextButton, OSL_ENSURE(pDlg, "Dialogdiet fail!"); if(pWindowState && !pWindowState->isEmpty()) pDlg->SetWindowState(*pWindowState); + + // Register for possible input field deletion while dialog is open + FieldDeletionModify aModify(pDlg); + GetDoc()->GetUnoCallBack()->Add(&aModify); + sal_Bool bRet = RET_CANCEL == pDlg->Execute(); + + // Dialog closed, remove modification listener + GetDoc()->GetUnoCallBack()->Remove(&aModify); + if(pWindowState) *pWindowState = pDlg->GetWindowState(); |