sw/inc/shellio.hxx                     |    2 
 sw/source/core/inc/SwXMLTextBlocks.hxx |    1 
 sw/source/core/inc/swblocks.hxx        |    1 
 sw/source/core/swg/SwXMLTextBlocks.cxx |   53 ++++++++++++++
 sw/source/core/swg/swblocks.cxx        |   10 ++
 sw/source/ui/misc/glossary.cxx         |  117 +++++++++++++++++++++++++++++++++
 sw/source/uibase/dochdl/gloshdl.cxx    |   22 ++++++
 sw/source/uibase/inc/gloshdl.hxx       |    2 
 sw/source/uibase/inc/glossary.hxx      |    3 
 sw/uiconfig/swriter/ui/autotext.ui     |    2 
 10 files changed, 213 insertions(+)

New commits:
commit 61f42c31b02c569ad22cad5e71b20cb0df8fd1f8
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Sun Nov 27 21:19:45 2022 +0000
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Mon Nov 28 17:28:10 2022 +0100

    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 <caol...@redhat.com>

diff --git a/sw/inc/shellio.hxx b/sw/inc/shellio.hxx
index e476b530fd8a..0fe3985597ef 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 bd6458e717d0..9132b5993e8f 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 d822acbe26ab..7bd877ad653d 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 f48d007db3c4..3bb108cbf22e 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 d9ccbe4c56c3..fb4769311724 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 2f3347d1e1ef..ae3ce4f06666 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 9f2e070162c4..4820584268aa 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 812609fdbba3..530d0b6bc4a0 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 ada07976450f..d0a99a86a664 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 ce59f4b19ade..19f3c636176f 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>

Reply via email to