Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "dbexchange.hxx"
21 : #include "dbtreelistbox.hxx"
22 : #include "dbtreemodel.hxx"
23 : #include "dbtreeview.hxx"
24 : #include "dbu_brw.hrc"
25 : #include "dbustrings.hrc"
26 : #include "QEnumTypes.hxx"
27 : #include "UITools.hxx"
28 : #include "unodatbr.hxx"
29 :
30 : #include <com/sun/star/frame/XStorable.hpp>
31 : #include <com/sun/star/sdb/CommandType.hpp>
32 : #include <com/sun/star/sdbc/XConnection.hpp>
33 :
34 : #include <connectivity/dbexception.hxx>
35 : #include <connectivity/dbtools.hxx>
36 : #include <cppuhelper/exc_hlp.hxx>
37 : #include <svx/dataaccessdescriptor.hxx>
38 : #include <tools/diagnose_ex.h>
39 : #include <osl/diagnose.h>
40 : #include "svtools/treelistentry.hxx"
41 :
42 : #include <algorithm>
43 : #include <functional>
44 : namespace dbaui
45 : {
46 :
47 : using namespace ::com::sun::star::uno;
48 : using namespace ::com::sun::star::sdb;
49 : using namespace ::com::sun::star::sdbc;
50 : using namespace ::com::sun::star::sdbcx;
51 : using namespace ::com::sun::star::beans;
52 : using namespace ::com::sun::star::util;
53 : using namespace ::com::sun::star::frame;
54 : using namespace ::com::sun::star::container;
55 : using namespace ::com::sun::star::lang;
56 : using namespace ::com::sun::star::form;
57 : using namespace ::com::sun::star::io;
58 : using namespace ::com::sun::star::i18n;
59 : using namespace ::com::sun::star::task;
60 : using namespace ::com::sun::star::datatransfer;
61 : using namespace ::dbtools;
62 : using namespace ::svx;
63 :
64 0 : TransferableHelper* SbaTableQueryBrowser::implCopyObject( SvTreeListEntry* _pApplyTo, sal_Int32 _nCommandType, bool _bAllowConnection )
65 : {
66 : try
67 : {
68 0 : OUString aName = GetEntryText( _pApplyTo );
69 0 : OUString aDSName = getDataSourceAcessor( m_pTreeView->getListBox().GetRootLevelParent( _pApplyTo ) );
70 :
71 0 : ODataClipboard* pData = NULL;
72 0 : SharedConnection xConnection;
73 0 : if ( CommandType::QUERY != _nCommandType )
74 : {
75 0 : if ( _bAllowConnection && !ensureConnection( _pApplyTo, xConnection) )
76 0 : return NULL;
77 0 : pData = new ODataClipboard(aDSName, _nCommandType, aName, xConnection, getNumberFormatter(), getORB());
78 : }
79 : else
80 0 : pData = new ODataClipboard(aDSName, _nCommandType, aName, getNumberFormatter(), getORB());
81 :
82 : // the ownership goes to ODataClipboards
83 0 : return pData;
84 : }
85 0 : catch(const SQLException& )
86 : {
87 0 : showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
88 : }
89 0 : catch( const Exception& )
90 : {
91 : DBG_UNHANDLED_EXCEPTION();
92 : }
93 0 : return NULL;
94 : }
95 0 : sal_Int8 SbaTableQueryBrowser::queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors )
96 : {
97 : // check if we're a table or query container
98 0 : SvTreeListEntry* pHitEntry = m_pTreeView->getListBox().GetEntry( _rEvt.maPosPixel );
99 :
100 0 : if ( pHitEntry ) // no drop if no entry was hit ....
101 : {
102 : // it must be a container
103 0 : EntryType eEntryType = getEntryType( pHitEntry );
104 0 : SharedConnection xConnection;
105 0 : if ( eEntryType == etTableContainer && ensureConnection( pHitEntry, xConnection ) && xConnection.is() )
106 : {
107 0 : Reference<XChild> xChild(xConnection,UNO_QUERY);
108 0 : Reference<XStorable> xStore;
109 0 : xStore = Reference<XStorable>( xChild.is() ? getDataSourceOrModel(xChild->getParent()) : Reference<XInterface>(),UNO_QUERY );
110 : // check for the concrete type
111 0 : if ( xStore.is() && !xStore->isReadonly() && ::std::any_of(_rFlavors.begin(),_rFlavors.end(),TAppSupportedSotFunctor(E_TABLE,true)) )
112 0 : return DND_ACTION_COPY;
113 0 : }
114 : }
115 :
116 0 : return DND_ACTION_NONE;
117 : }
118 0 : sal_Int8 SbaTableQueryBrowser::executeDrop( const ExecuteDropEvent& _rEvt )
119 : {
120 0 : SvTreeListEntry* pHitEntry = m_pTreeView->getListBox().GetEntry( _rEvt.maPosPixel );
121 0 : EntryType eEntryType = getEntryType( pHitEntry );
122 0 : if (!isContainer(eEntryType))
123 : {
124 : OSL_FAIL("SbaTableQueryBrowser::executeDrop: what the hell did queryDrop do?");
125 : // queryDrop should not have allowed us to reach this situation ....
126 0 : return DND_ACTION_NONE;
127 : }
128 : // a TransferableDataHelper for accessing the dropped data
129 0 : TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable);
130 :
131 : // reset the data of the previous async drop (if any)
132 0 : if ( m_nAsyncDrop )
133 0 : Application::RemoveUserEvent(m_nAsyncDrop);
134 :
135 0 : m_nAsyncDrop = 0;
136 0 : m_aAsyncDrop.aDroppedData.clear();
137 0 : m_aAsyncDrop.nType = E_TABLE;
138 0 : m_aAsyncDrop.nAction = _rEvt.mnAction;
139 0 : m_aAsyncDrop.bError = false;
140 0 : m_aAsyncDrop.bHtml = false;
141 0 : m_aAsyncDrop.pDroppedAt = NULL;
142 0 : m_aAsyncDrop.aUrl.clear();
143 :
144 : // loop through the available formats and see what we can do ...
145 : // first we have to check if it is our own format, if not we have to copy the stream :-(
146 0 : if ( ODataAccessObjectTransferable::canExtractObjectDescriptor(aDroppedData.GetDataFlavorExVector()) )
147 : {
148 0 : m_aAsyncDrop.aDroppedData = ODataAccessObjectTransferable::extractObjectDescriptor(aDroppedData);
149 0 : m_aAsyncDrop.pDroppedAt = pHitEntry;
150 :
151 : // asynchron because we some dialogs and we aren't allowed to show them while in D&D
152 0 : m_nAsyncDrop = Application::PostUserEvent(LINK(this, SbaTableQueryBrowser, OnAsyncDrop));
153 0 : return DND_ACTION_COPY;
154 : }
155 : else
156 : {
157 0 : SharedConnection xDestConnection;
158 0 : if ( ensureConnection( pHitEntry, xDestConnection )
159 0 : && xDestConnection.is()
160 0 : && m_aTableCopyHelper.copyTagTable( aDroppedData, m_aAsyncDrop, xDestConnection )
161 : )
162 : {
163 0 : m_aAsyncDrop.pDroppedAt = pHitEntry;
164 :
165 : // asynchron because we some dialogs and we aren't allowed to show them while in D&D
166 0 : m_nAsyncDrop = Application::PostUserEvent(LINK(this, SbaTableQueryBrowser, OnAsyncDrop));
167 0 : return DND_ACTION_COPY;
168 0 : }
169 : }
170 :
171 0 : return DND_ACTION_NONE;
172 : }
173 :
174 0 : bool SbaTableQueryBrowser::requestDrag( sal_Int8 /*_nAction*/, const Point& _rPosPixel )
175 : {
176 : // get the affected list entry
177 : // ensure that the entry which the user clicked at is selected
178 0 : SvTreeListEntry* pHitEntry = m_pTreeView->getListBox().GetEntry( _rPosPixel );
179 0 : if (!pHitEntry)
180 : // no drag of no entry was hit ....
181 0 : return false;
182 :
183 : // it must be a query/table
184 0 : EntryType eEntryType = getEntryType( pHitEntry );
185 0 : if (!isObject(eEntryType))
186 0 : return false;
187 :
188 0 : TransferableHelper* pTransfer = implCopyObject( pHitEntry, ( etTableOrView == eEntryType ) ? CommandType::TABLE : CommandType::QUERY);
189 0 : Reference< XTransferable> xEnsureDelete = pTransfer;
190 :
191 0 : if (pTransfer)
192 0 : pTransfer->StartDrag( &m_pTreeView->getListBox(), DND_ACTION_COPY );
193 :
194 0 : return NULL != pTransfer;
195 : }
196 0 : IMPL_LINK_NOARG(SbaTableQueryBrowser, OnCopyEntry)
197 : {
198 0 : SvTreeListEntry* pSelected = m_pTreeView->getListBox().FirstSelected();
199 0 : if( isEntryCopyAllowed( pSelected ) )
200 0 : copyEntry( pSelected );
201 0 : return 0;
202 : }
203 0 : bool SbaTableQueryBrowser::isEntryCopyAllowed(SvTreeListEntry* _pEntry) const
204 : {
205 0 : EntryType eType = getEntryType(_pEntry);
206 0 : return ( eType == etTableOrView || eType == etQuery );
207 : }
208 0 : void SbaTableQueryBrowser::copyEntry(SvTreeListEntry* _pEntry)
209 : {
210 0 : TransferableHelper* pTransfer = NULL;
211 0 : Reference< XTransferable> aEnsureDelete;
212 0 : EntryType eType = getEntryType(_pEntry);
213 0 : pTransfer = implCopyObject( _pEntry, eType == etQuery ? CommandType::QUERY : CommandType::TABLE);
214 0 : aEnsureDelete = pTransfer;
215 0 : if (pTransfer)
216 0 : pTransfer->CopyToClipboard(getView());
217 0 : }
218 0 : IMPL_LINK_NOARG( SbaTableQueryBrowser, OnAsyncDrop )
219 : {
220 0 : m_nAsyncDrop = 0;
221 0 : SolarMutexGuard aSolarGuard;
222 0 : ::osl::MutexGuard aGuard( getMutex() );
223 :
224 0 : if ( m_aAsyncDrop.nType == E_TABLE )
225 : {
226 0 : SharedConnection xDestConnection;
227 0 : if ( ensureConnection( m_aAsyncDrop.pDroppedAt, xDestConnection ) && xDestConnection.is() )
228 : {
229 0 : SvTreeListEntry* pDataSourceEntry = m_pTreeView->getListBox().GetRootLevelParent(m_aAsyncDrop.pDroppedAt);
230 0 : m_aTableCopyHelper.asyncCopyTagTable( m_aAsyncDrop, getDataSourceAcessor( pDataSourceEntry ), xDestConnection );
231 0 : }
232 : }
233 :
234 0 : m_aAsyncDrop.aDroppedData.clear();
235 :
236 0 : return 0L;
237 : }
238 2 : void SbaTableQueryBrowser::clearTreeModel()
239 : {
240 2 : if (m_pTreeModel)
241 : {
242 : // clear the user data of the tree model
243 1 : SvTreeListEntry* pEntryLoop = m_pTreeModel->First();
244 6 : while (pEntryLoop)
245 : {
246 4 : DBTreeListUserData* pData = static_cast<DBTreeListUserData*>(pEntryLoop->GetUserData());
247 4 : if(pData)
248 : {
249 4 : pEntryLoop->SetUserData(NULL);
250 4 : Reference< XContainer > xContainer(pData->xContainer, UNO_QUERY);
251 4 : if (xContainer.is())
252 1 : xContainer->removeContainerListener(this);
253 :
254 4 : if ( pData->xConnection.is() )
255 : {
256 : OSL_ENSURE( impl_isDataSourceEntry( pEntryLoop ), "SbaTableQueryBrowser::clearTreeModel: no data source entry, but a connection?" );
257 : // connections are to be stored *only* at the data source entries
258 1 : impl_releaseConnection( pData->xConnection );
259 : }
260 :
261 4 : delete pData;
262 : }
263 4 : pEntryLoop = m_pTreeModel->Next(pEntryLoop);
264 : }
265 : }
266 2 : m_pCurrentlyDisplayed = NULL;
267 2 : }
268 36 : } // namespace dbaui
269 :
270 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|