1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <dbexchange.hxx>
21 #include <dbtreelistbox.hxx>
22 #include "dbtreemodel.hxx"
23 #include <UITools.hxx>
24 #include <unodatbr.hxx>
26 #include <com/sun/star/frame/XStorable.hpp>
27 #include <com/sun/star/sdb/CommandType.hpp>
28 #include <com/sun/star/sdbc/SQLException.hpp>
30 #include <connectivity/dbexception.hxx>
31 #include <connectivity/dbtools.hxx>
32 #include <cppuhelper/exc_hlp.hxx>
33 #include <svx/dataaccessdescriptor.hxx>
34 #include <comphelper/diagnose_ex.hxx>
35 #include <osl/diagnose.h>
36 #include <vcl/svapp.hxx>
43 using namespace ::com::sun::star::uno
;
44 using namespace ::com::sun::star::sdb
;
45 using namespace ::com::sun::star::sdbc
;
46 using namespace ::com::sun::star::frame
;
47 using namespace ::com::sun::star::container
;
48 using namespace ::com::sun::star::datatransfer
;
49 using namespace ::dbtools
;
50 using namespace ::svx
;
52 bool SbaTableQueryBrowser::implCopyObject(ODataClipboard
& rExchange
, const weld::TreeIter
& rApplyTo
, sal_Int32 nCommandType
)
56 OUString aName
= GetEntryText(rApplyTo
);
57 std::unique_ptr
<weld::TreeIter
> xRootEntry(m_pTreeView
->GetRootLevelParent(&rApplyTo
));
58 OUString aDSName
= getDataSourceAccessor(*xRootEntry
);
60 SharedConnection xConnection
;
61 if ( CommandType::QUERY
!= nCommandType
)
63 if (!ensureConnection(&rApplyTo
, xConnection
))
65 rExchange
.Update(aDSName
, nCommandType
, aName
, xConnection
, getNumberFormatter(), getORB());
68 rExchange
.Update(aDSName
, nCommandType
, aName
, getNumberFormatter(), getORB());
70 // the ownership goes to ODataClipboards
73 catch(const SQLException
& )
75 showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
77 catch( const Exception
& )
79 DBG_UNHANDLED_EXCEPTION("dbaccess");
84 sal_Int8
SbaTableQueryBrowser::queryDrop( const AcceptDropEvent
& _rEvt
, const DataFlavorExVector
& _rFlavors
)
86 // check if we're a table or query container
87 weld::TreeView
& rTreeView
= m_pTreeView
->GetWidget();
88 std::unique_ptr
<weld::TreeIter
> xHitEntry(rTreeView
.make_iterator());
89 // get_dest_row_at_pos with false cause no drop if no entry was hit exactly
90 if (rTreeView
.get_dest_row_at_pos(_rEvt
.maPosPixel
, xHitEntry
.get(), false))
92 // it must be a container
93 EntryType eEntryType
= getEntryType(*xHitEntry
);
94 SharedConnection xConnection
;
95 if ( eEntryType
== etTableContainer
&& ensureConnection(xHitEntry
.get(), xConnection
) && xConnection
.is())
97 Reference
<XChild
> xChild(xConnection
,UNO_QUERY
);
98 Reference
<XStorable
> xStore
;
100 xStore
.set( getDataSourceOrModel(xChild
->getParent()), UNO_QUERY
);
101 // check for the concrete type
102 if ( xStore
.is() && !xStore
->isReadonly() && std::any_of(_rFlavors
.begin(),_rFlavors
.end(),TAppSupportedSotFunctor(E_TABLE
)) )
103 return DND_ACTION_COPY
;
107 return DND_ACTION_NONE
;
109 sal_Int8
SbaTableQueryBrowser::executeDrop( const ExecuteDropEvent
& _rEvt
)
111 weld::TreeView
& rTreeView
= m_pTreeView
->GetWidget();
112 std::unique_ptr
<weld::TreeIter
> xHitEntry(rTreeView
.make_iterator());
113 // get_dest_row_at_pos with false cause no drop if no entry was hit exactly
114 if (!rTreeView
.get_dest_row_at_pos(_rEvt
.maPosPixel
, xHitEntry
.get(), false))
115 return DND_ACTION_NONE
;
116 EntryType eEntryType
= getEntryType(*xHitEntry
);
117 if (!isContainer(eEntryType
))
119 OSL_FAIL("SbaTableQueryBrowser::executeDrop: what the hell did queryDrop do?");
120 // queryDrop should not have allowed us to reach this situation...
121 return DND_ACTION_NONE
;
123 // a TransferableDataHelper for accessing the dropped data
124 TransferableDataHelper
aDroppedData(_rEvt
.maDropEvent
.Transferable
);
126 // reset the data of the previous async drop (if any)
128 Application::RemoveUserEvent(m_nAsyncDrop
);
130 m_nAsyncDrop
= nullptr;
131 m_aAsyncDrop
.aDroppedData
.clear();
132 m_aAsyncDrop
.nType
= E_TABLE
;
133 m_aAsyncDrop
.nAction
= _rEvt
.mnAction
;
134 m_aAsyncDrop
.bError
= false;
135 m_aAsyncDrop
.bHtml
= false;
136 m_aAsyncDrop
.xDroppedAt
.reset();
137 m_aAsyncDrop
.aUrl
.clear();
139 // loop through the available formats and see what we can do ...
140 // first we have to check if it is our own format, if not we have to copy the stream :-(
141 if ( ODataAccessObjectTransferable::canExtractObjectDescriptor(aDroppedData
.GetDataFlavorExVector()) )
143 m_aAsyncDrop
.aDroppedData
= ODataAccessObjectTransferable::extractObjectDescriptor(aDroppedData
);
144 m_aAsyncDrop
.xDroppedAt
= std::move(xHitEntry
);
146 // asynchron because we some dialogs and we aren't allowed to show them while in D&D
147 m_nAsyncDrop
= Application::PostUserEvent(LINK(this, SbaTableQueryBrowser
, OnAsyncDrop
));
148 return DND_ACTION_COPY
;
152 SharedConnection xDestConnection
;
153 if ( ensureConnection( xHitEntry
.get(), xDestConnection
)
154 && xDestConnection
.is()
155 && m_aTableCopyHelper
.copyTagTable( aDroppedData
, m_aAsyncDrop
, xDestConnection
)
158 m_aAsyncDrop
.xDroppedAt
= std::move(xHitEntry
);
160 // asynchron because we some dialogs and we aren't allowed to show them while in D&D
161 m_nAsyncDrop
= Application::PostUserEvent(LINK(this, SbaTableQueryBrowser
, OnAsyncDrop
));
162 return DND_ACTION_COPY
;
166 return DND_ACTION_NONE
;
169 bool SbaTableQueryBrowser::requestDrag(const weld::TreeIter
& rEntry
)
171 // it must be a query/table
172 EntryType eEntryType
= getEntryType(rEntry
);
173 if (!isObject(eEntryType
))
176 ODataClipboard
& rExchange
= static_cast<ODataClipboard
&>(m_pTreeView
->GetDataTransfer());
177 return implCopyObject(rExchange
, rEntry
, (etTableOrView
== eEntryType
) ? CommandType::TABLE
: CommandType::QUERY
);
180 IMPL_LINK_NOARG(SbaTableQueryBrowser
, OnCopyEntry
, LinkParamNone
*, void)
182 weld::TreeView
& rTreeView
= m_pTreeView
->GetWidget();
183 std::unique_ptr
<weld::TreeIter
> xSelected
= rTreeView
.make_iterator();
184 if (rTreeView
.get_selected(xSelected
.get()) && isEntryCopyAllowed(*xSelected
))
185 copyEntry(*xSelected
);
188 bool SbaTableQueryBrowser::isEntryCopyAllowed(const weld::TreeIter
& rEntry
) const
190 EntryType eType
= getEntryType(rEntry
);
191 return ( eType
== etTableOrView
|| eType
== etQuery
);
194 void SbaTableQueryBrowser::copyEntry(const weld::TreeIter
& rEntry
)
196 EntryType eType
= getEntryType(rEntry
);
197 rtl::Reference
<ODataClipboard
> xTransfer(new ODataClipboard
);
198 if (implCopyObject(*xTransfer
, rEntry
, eType
== etQuery
? CommandType::QUERY
: CommandType::TABLE
))
199 xTransfer
->CopyToClipboard(getView());
202 IMPL_LINK_NOARG( SbaTableQueryBrowser
, OnAsyncDrop
, void*, void )
204 m_nAsyncDrop
= nullptr;
205 SolarMutexGuard aSolarGuard
;
206 ::osl::MutexGuard
aGuard( getMutex() );
208 if ( m_aAsyncDrop
.nType
== E_TABLE
)
210 SharedConnection xDestConnection
;
211 if ( ensureConnection(m_aAsyncDrop
.xDroppedAt
.get(), xDestConnection
) && xDestConnection
.is())
213 std::unique_ptr
<weld::TreeIter
> xDataSourceEntry
=
214 m_pTreeView
->GetRootLevelParent(m_aAsyncDrop
.xDroppedAt
.get());
215 m_aTableCopyHelper
.asyncCopyTagTable(m_aAsyncDrop
, getDataSourceAccessor(*xDataSourceEntry
), xDestConnection
);
219 m_aAsyncDrop
.aDroppedData
.clear();
222 void SbaTableQueryBrowser::clearTreeModel()
224 weld::TreeView
& rTreeView
= m_pTreeView
->GetWidget();
225 rTreeView
.all_foreach([this, &rTreeView
](weld::TreeIter
& rEntryLoop
){
226 // clear the user data of the tree model
227 DBTreeListUserData
* pData
= weld::fromId
<DBTreeListUserData
*>(rTreeView
.get_id(rEntryLoop
));
230 rTreeView
.set_id(rEntryLoop
, OUString());
231 Reference
<XContainer
> xContainer(pData
->xContainer
, UNO_QUERY
);
233 xContainer
->removeContainerListener(this);
235 if (pData
->xConnection
.is())
237 // connections are to be stored *only* at the data source entries
238 impl_releaseConnection(pData
->xConnection
);
246 m_xCurrentlyDisplayed
.reset();
250 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */