Resolves: tdf#147203 allow dnd between autotext categories
restores various methods removed as unused since original
regression at
commit 4830a1bae89a8ed60696503e315ffd42c70dff74
Date: Thu May 30 16:12:23 2019 +0100
weld SwGlossaryDlg
Change-Id: I5c6186b9f45f3c0957926de2861eb6bc76dda73d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143363
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/sw/inc/shellio.hxx b/sw/inc/shellio.hxx
index e476b53..0fe3985 100644
--- a/sw/inc/shellio.hxx
+++ b/sw/inc/shellio.hxx
@@ -327,6 +327,8 @@ public:
bool Delete( sal_uInt16 );
void Rename( sal_uInt16, const OUString*, const OUString* );
ErrCode const & CopyBlock( SwTextBlocks const & rSource, OUString& rSrcShort,
const OUString& rLong );
bool BeginGetDoc( sal_uInt16 ); // Read text modules.
void EndGetDoc(); // Release text modules.
diff --git a/sw/source/core/inc/SwXMLTextBlocks.hxx b/sw/source/core/inc/SwXMLTextBlocks.hxx
index bd6458e..9132b59 100644
--- a/sw/source/core/inc/SwXMLTextBlocks.hxx
+++ b/sw/source/core/inc/SwXMLTextBlocks.hxx
@@ -61,6 +61,7 @@ public:
virtual ~SwXMLTextBlocks() override;
virtual ErrCode Delete( sal_uInt16 ) override;
virtual ErrCode Rename( sal_uInt16, const OUString& ) override;
virtual ErrCode CopyBlock( SwImpBlocks& rImp, OUString& rShort, const OUString& rLong) override;
virtual void ClearDoc() override;
virtual ErrCode GetDoc( sal_uInt16 ) override;
virtual ErrCode BeginPutDoc( const OUString&, const OUString& ) override;
diff --git a/sw/source/core/inc/swblocks.hxx b/sw/source/core/inc/swblocks.hxx
index d822acb..7bd877a 100644
--- a/sw/source/core/inc/swblocks.hxx
+++ b/sw/source/core/inc/swblocks.hxx
@@ -106,6 +106,7 @@ public:
virtual ErrCode Delete( sal_uInt16 ) = 0;
virtual ErrCode Rename( sal_uInt16, const OUString& ) = 0;
virtual ErrCode CopyBlock( SwImpBlocks& rImp, OUString& rShort, const OUString& rLong) = 0;
virtual ErrCode GetDoc( sal_uInt16 ) = 0;
virtual ErrCode BeginPutDoc( const OUString&, const OUString& ) = 0;
virtual ErrCode PutDoc() = 0;
diff --git a/sw/source/core/swg/SwXMLTextBlocks.cxx b/sw/source/core/swg/SwXMLTextBlocks.cxx
index f48d007..3bb108c 100644
--- a/sw/source/core/swg/SwXMLTextBlocks.cxx
+++ b/sw/source/core/swg/SwXMLTextBlocks.cxx
@@ -232,6 +232,59 @@ ErrCode SwXMLTextBlocks::Rename( sal_uInt16 nIdx, const OUString& rNewShort )
return ERRCODE_NONE;
}
ErrCode SwXMLTextBlocks::CopyBlock( SwImpBlocks& rDestImp, OUString& rShort,
const OUString& rLong)
{
ErrCode nError = ERRCODE_NONE;
OpenFile();
rDestImp.OpenFile(false);
const OUString aGroup( rShort );
bool bTextOnly = IsOnlyTextBlock ( rShort ) ;//pImp->pBlkRoot->IsStream( aGroup );
sal_uInt16 nIndex = GetIndex ( rShort );
OUString sPackageName( GetPackageName (nIndex) );
OUString sDestShortName( sPackageName );
sal_uInt16 nIdx = 0;
OSL_ENSURE( m_xBlkRoot.is(), "No storage set" );
if(!m_xBlkRoot.is())
return ERR_SWG_WRITE_ERROR;
uno::Reference < container::XNameAccess > xAccess(static_cast<SwXMLTextBlocks&>(rDestImp).m_xBlkRoot);
while ( xAccess->hasByName( sDestShortName ) )
{
++nIdx;
// If someone is that crazy ...
if(USHRT_MAX == nIdx)
{
CloseFile();
rDestImp.CloseFile();
return ERR_SWG_WRITE_ERROR;
}
sDestShortName = sPackageName + OUString::number( nIdx );
}
try
{
uno::Reference < embed::XStorage > rSourceRoot = m_xBlkRoot->openStorageElement( aGroup, embed::ElementModes::READ );
uno::Reference < embed::XStorage > rDestRoot = static_cast<SwXMLTextBlocks&>(rDestImp).m_xBlkRoot->openStorageElement( sDestShortName, embed::ElementModes::READWRITE );
rSourceRoot->copyToStorage( rDestRoot );
}
catch (const uno::Exception&)
{
nError = ERR_SWG_WRITE_ERROR;
}
if(!nError)
{
rShort = sDestShortName;
static_cast<SwXMLTextBlocks&>(rDestImp).AddName( rShort, rLong, bTextOnly );
static_cast<SwXMLTextBlocks&>(rDestImp).MakeBlockList();
}
CloseFile();
rDestImp.CloseFile();
return nError;
}
ErrCode SwXMLTextBlocks::StartPutBlock( const OUString& rShort, const OUString& rPackageName )
{
OSL_ENSURE( m_xBlkRoot.is(), "No storage set" );
diff --git a/sw/source/core/swg/swblocks.cxx b/sw/source/core/swg/swblocks.cxx
index d9ccbe4..fb47693 100644
--- a/sw/source/core/swg/swblocks.cxx
+++ b/sw/source/core/swg/swblocks.cxx
@@ -346,6 +346,16 @@ void SwTextBlocks::Rename( sal_uInt16 n, const OUString* s, const OUString* l )
m_pImp->Touch();
}
ErrCode const & SwTextBlocks::CopyBlock( SwTextBlocks const & rSource, OUString& rSrcShort,
const OUString& rLong )
{
if (m_pImp->m_bInPutMuchBlocks)
m_nErr = ERR_SWG_INTERNAL_ERROR;
else
m_nErr = m_pImp->CopyBlock(*rSource.m_pImp, rSrcShort, rLong);
return m_nErr;
}
bool SwTextBlocks::BeginGetDoc( sal_uInt16 n )
{
if( m_pImp && !m_pImp->m_bInPutMuchBlocks )
diff --git a/sw/source/ui/misc/glossary.cxx b/sw/source/ui/misc/glossary.cxx
index 2f3347d..ae3ce4f 100644
--- a/sw/source/ui/misc/glossary.cxx
+++ b/sw/source/ui/misc/glossary.cxx
@@ -22,6 +22,7 @@
#include <o3tl/any.hxx>
#include <vcl/event.hxx>
#include <vcl/svapp.hxx>
#include <vcl/transfer.hxx>
#include <vcl/weld.hxx>
#include <svl/stritem.hxx>
#include <svl/macitem.hxx>
@@ -176,6 +177,117 @@ IMPL_LINK(SwGlossaryDlg, TextFilterHdl, OUString&, rTest, bool)
return true;
}
class SwGlossaryDropTarget : public DropTargetHelper
{
private:
weld::TreeView& m_rTreeView;
SwGlossaryHdl* m_pGlosHdl;
virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override
{
weld::TreeView* pSource = m_rTreeView.get_drag_source();
if (!pSource || pSource != &m_rTreeView)
return DND_ACTION_NONE;
std::unique_ptr<weld::TreeIter> xSelected(pSource->make_iterator());
bool bSelected = pSource->get_selected(xSelected.get());
if (!bSelected)
return DND_ACTION_NONE;
while (pSource->get_iter_depth(*xSelected))
(void)pSource->iter_parent(*xSelected);
GroupUserData* pSrcRootData = weld::fromId<GroupUserData*>(pSource->get_id(*xSelected));
GroupUserData* pDestRootData = nullptr;
std::unique_ptr<weld::TreeIter> xDestEntry(m_rTreeView.make_iterator());
bool bEntry = m_rTreeView.get_dest_row_at_pos(rEvt.maPosPixel, xDestEntry.get(), true);
if (bEntry)
{
while (m_rTreeView.get_iter_depth(*xDestEntry))
(void)m_rTreeView.iter_parent(*xDestEntry);
pDestRootData = weld::fromId<GroupUserData*>(m_rTreeView.get_id(*xDestEntry));
}
if (pDestRootData == pSrcRootData)
return DND_ACTION_NONE;
sal_uInt8 nRet = DND_ACTION_COPY;
const bool bCheckForMove = rEvt.mnAction & DND_ACTION_MOVE;
if (bCheckForMove && !pSrcRootData->bReadonly)
nRet |= DND_ACTION_MOVE;
return nRet;
}
virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override
{
weld::TreeView* pSource = m_rTreeView.get_drag_source();
if (!pSource)
return DND_ACTION_NONE;
std::unique_ptr<weld::TreeIter> xDestEntry(m_rTreeView.make_iterator());
bool bEntry = m_rTreeView.get_dest_row_at_pos(rEvt.maPosPixel, xDestEntry.get(), true);
if (!bEntry)
return DND_ACTION_NONE;
std::unique_ptr<weld::TreeIter> xSelected(pSource->make_iterator());
bool bSelected = pSource->get_selected(xSelected.get());
if (!bSelected)
return DND_ACTION_NONE;
std::unique_ptr<weld::TreeIter> xSrcParent(pSource->make_iterator(xSelected.get()));
while (pSource->get_iter_depth(*xSrcParent))
(void)pSource->iter_parent(*xSrcParent);
std::unique_ptr<weld::TreeIter> xDestParent(pSource->make_iterator(xDestEntry.get()));
while (pSource->get_iter_depth(*xDestParent))
(void)pSource->iter_parent(*xDestParent);
GroupUserData* pSrcParent = weld::fromId<GroupUserData*>(pSource->get_id(*xSrcParent));
GroupUserData* pDestParent = weld::fromId<GroupUserData*>(m_rTreeView.get_id(*xDestParent));
if (pDestParent != pSrcParent)
{
weld::WaitObject aBusy(&m_rTreeView);
OUString sSourceGroup = pSrcParent->sGroupName
+ OUStringChar(GLOS_DELIM)
+ OUString::number(pSrcParent->nPathIdx);
m_pGlosHdl->SetCurGroup(sSourceGroup);
OUString sTitle(pSource->get_text(*xSelected));
OUString sShortName(pSource->get_id(*xSelected));
OUString sDestName = pDestParent->sGroupName
+ OUStringChar(GLOS_DELIM)
+ OUString::number(pDestParent->nPathIdx);
bool bIsMove = rEvt.mnAction & DND_ACTION_MOVE;
const bool bRet = m_pGlosHdl->CopyOrMove(sSourceGroup, sShortName,
sDestName, sTitle, bIsMove);
if(bRet)
{
m_rTreeView.insert(xDestParent.get(), -1, &sTitle, &sShortName,
nullptr, nullptr, false, nullptr);
if (bIsMove)
{
pSource->remove(*xSelected);
}
}
}
return DND_ACTION_NONE;
}
public:
SwGlossaryDropTarget(weld::TreeView& rTreeView, SwGlossaryHdl* pGlosHdl)
: DropTargetHelper(rTreeView.get_drop_target())
, m_rTreeView(rTreeView)
, m_pGlosHdl(pGlosHdl)
{
}
};
SwGlossaryDlg::SwGlossaryDlg(SfxViewFrame const * pViewFrame,
SwGlossaryHdl * pGlosHdl, SwWrtShell *pWrtShell)
: SfxDialogController(pViewFrame->GetFrameWeld(), "modules/swriter/ui/autotext.ui", "AutoTextDialog")
@@ -221,6 +333,11 @@ SwGlossaryDlg::SwGlossaryDlg(SfxViewFrame const * pViewFrame,
m_xCategoryBox->connect_row_activated(LINK(this, SwGlossaryDlg, NameDoubleClick));
m_xCategoryBox->connect_changed(LINK(this, SwGlossaryDlg, GrpSelect));
m_xCategoryBox->connect_key_press(LINK(this, SwGlossaryDlg, KeyInputHdl));
m_xDropTarget.reset(new SwGlossaryDropTarget(*m_xCategoryBox, pGlosHdl));
rtl::Reference<TransferDataContainer> xHelper(new TransferDataContainer);
m_xCategoryBox->enable_drag_source(xHelper, DND_ACTION_COPYMOVE);
m_xBibBtn->connect_clicked(LINK(this,SwGlossaryDlg,BibHdl));
m_xInsertBtn->connect_clicked(LINK(this,SwGlossaryDlg,InsertHdl));
diff --git a/sw/source/uibase/dochdl/gloshdl.cxx b/sw/source/uibase/dochdl/gloshdl.cxx
index 9f2e070..4820584 100644
--- a/sw/source/uibase/dochdl/gloshdl.cxx
+++ b/sw/source/uibase/dochdl/gloshdl.cxx
@@ -196,6 +196,28 @@ void SwGlossaryHdl::RenameGroup(const OUString& rOld, OUString& rNew, const OUSt
}
}
bool SwGlossaryHdl::CopyOrMove(const OUString& rSourceGroupName, OUString& rSourceShortName,
const OUString& rDestGroupName, const OUString& rLongName, bool bMove)
{
std::unique_ptr<SwTextBlocks> pSourceGroup = m_rStatGlossaries.GetGroupDoc(rSourceGroupName);
std::unique_ptr<SwTextBlocks> pDestGroup = m_rStatGlossaries.GetGroupDoc(rDestGroupName);
if (pDestGroup->IsReadOnly() || (bMove && pSourceGroup->IsReadOnly()) )
{
return false;
}
//The index must be determined here because rSourceShortName maybe changed in CopyBlock
sal_uInt16 nDeleteIdx = pSourceGroup->GetIndex( rSourceShortName );
OSL_ENSURE(USHRT_MAX != nDeleteIdx, "entry not found");
ErrCode nRet = pSourceGroup->CopyBlock( *pDestGroup, rSourceShortName, rLongName );
if(!nRet && bMove)
{
// the index must be existing
nRet = pSourceGroup->Delete( nDeleteIdx ) ? ERRCODE_NONE : ErrCode(1);
}
return !nRet;
}
// delete an autotext-file-group
bool SwGlossaryHdl::DelGroup(const OUString &rGrpName)
{
diff --git a/sw/source/uibase/inc/gloshdl.hxx b/sw/source/uibase/inc/gloshdl.hxx
index 812609f..530d0b6 100644
--- a/sw/source/uibase/inc/gloshdl.hxx
+++ b/sw/source/uibase/inc/gloshdl.hxx
@@ -62,6 +62,8 @@ public:
bool Rename( const OUString& rOldShortName, const OUString& rNewShortName,
const OUString& rNewName);
bool CopyOrMove( const OUString& rSourceGroupName, OUString& rSourceShortName,
const OUString& rDestGroupName, const OUString& rLongName, bool bMove );
bool HasShortName(const OUString &rShortName) const;
// when NewGlossary is called from Basic then the previously set group should
// be newly created if applicable.
diff --git a/sw/source/uibase/inc/glossary.hxx b/sw/source/uibase/inc/glossary.hxx
index ada0797..d0a99a86a 100644
--- a/sw/source/uibase/inc/glossary.hxx
+++ b/sw/source/uibase/inc/glossary.hxx
@@ -39,6 +39,8 @@ class SwOneExampleFrame;
const short RET_EDIT = 100;
class SwGlossaryDropTarget;
class SwGlossaryDlg final : public SfxDialogController
{
friend class SwNewGlosNameDlg;
@@ -76,6 +78,7 @@ class SwGlossaryDlg final : public SfxDialogController
std::unique_ptr<weld::Button> m_xPathBtn;
std::unique_ptr<SwOneExampleFrame> m_xExampleFrame;
std::unique_ptr<weld::CustomWeld> m_xExampleFrameWin;
std::unique_ptr<SwGlossaryDropTarget> m_xDropTarget;
void EnableShortName(bool bOn = true);
void ShowPreview();
diff --git a/sw/uiconfig/swriter/ui/autotext.ui b/sw/uiconfig/swriter/ui/autotext.ui
index ce59f4b..19f3c63 100644
--- a/sw/uiconfig/swriter/ui/autotext.ui
+++ b/sw/uiconfig/swriter/ui/autotext.ui
@@ -484,7 +484,9 @@
<property name="model">liststore1</property>
<property name="headers-visible">False</property>
<property name="headers-clickable">False</property>
<property name="reorderable">True</property>
<property name="search-column">0</property>
<property name="enable-tree-lines">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection1"/>
</child>