1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_dbaccess.hxx" 26 27 #include "dbexchange.hxx" 28 #include "dbtreelistbox.hxx" 29 #include "dbtreemodel.hxx" 30 #include "dbtreeview.hxx" 31 #include "dbu_brw.hrc" 32 #include "dbustrings.hrc" 33 #include "QEnumTypes.hxx" 34 #include "UITools.hxx" 35 #include "unodatbr.hxx" 36 37 /** === begin UNO includes === **/ 38 #include <com/sun/star/frame/XStorable.hpp> 39 #include <com/sun/star/sdb/CommandType.hpp> 40 #include <com/sun/star/sdbc/XConnection.hpp> 41 /** === end UNO includes === **/ 42 43 #include <connectivity/dbexception.hxx> 44 #include <connectivity/dbtools.hxx> 45 #include <cppuhelper/exc_hlp.hxx> 46 #include <svtools/treelist.hxx> 47 #include <svx/dataaccessdescriptor.hxx> 48 #include <tools/diagnose_ex.h> 49 50 #include <functional> 51 // ......................................................................... 52 namespace dbaui 53 { 54 // ......................................................................... 55 56 using namespace ::com::sun::star::uno; 57 using namespace ::com::sun::star::sdb; 58 using namespace ::com::sun::star::sdbc; 59 using namespace ::com::sun::star::sdbcx; 60 using namespace ::com::sun::star::beans; 61 using namespace ::com::sun::star::util; 62 using namespace ::com::sun::star::frame; 63 using namespace ::com::sun::star::container; 64 using namespace ::com::sun::star::lang; 65 using namespace ::com::sun::star::form; 66 using namespace ::com::sun::star::io; 67 using namespace ::com::sun::star::i18n; 68 using namespace ::com::sun::star::task; 69 using namespace ::com::sun::star::datatransfer; 70 using namespace ::dbtools; 71 using namespace ::svx; 72 73 // ----------------------------------------------------------------------------- 74 TransferableHelper* SbaTableQueryBrowser::implCopyObject( SvLBoxEntry* _pApplyTo, sal_Int32 _nCommandType, sal_Bool _bAllowConnection ) 75 { 76 try 77 { 78 ::rtl::OUString aName = GetEntryText( _pApplyTo ); 79 ::rtl::OUString aDSName = getDataSourceAcessor( m_pTreeView->getListBox().GetRootLevelParent( _pApplyTo ) ); 80 81 ODataClipboard* pData = NULL; 82 SharedConnection xConnection; 83 if ( CommandType::QUERY != _nCommandType ) 84 { 85 if ( _bAllowConnection && !ensureConnection( _pApplyTo, xConnection) ) 86 return NULL; 87 pData = new ODataClipboard(aDSName, _nCommandType, aName, xConnection, getNumberFormatter(), getORB()); 88 } 89 else 90 pData = new ODataClipboard(aDSName, _nCommandType, aName, getNumberFormatter(), getORB()); 91 92 // the owner ship goes to ODataClipboards 93 return pData; 94 } 95 catch(const SQLException& ) 96 { 97 showError( SQLExceptionInfo( ::cppu::getCaughtException() ) ); 98 } 99 catch( const Exception& ) 100 { 101 DBG_UNHANDLED_EXCEPTION(); 102 } 103 return NULL; 104 } 105 // ----------------------------------------------------------------------------- 106 sal_Int8 SbaTableQueryBrowser::queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors ) 107 { 108 // check if we're a table or query container 109 SvLBoxEntry* pHitEntry = m_pTreeView->getListBox().GetEntry( _rEvt.maPosPixel ); 110 111 if ( pHitEntry ) // no drop if no entry was hit .... 112 { 113 // it must be a container 114 EntryType eEntryType = getEntryType( pHitEntry ); 115 SharedConnection xConnection; 116 if ( eEntryType == etTableContainer && ensureConnection( pHitEntry, xConnection ) && xConnection.is() ) 117 { 118 Reference<XChild> xChild(xConnection,UNO_QUERY); 119 Reference<XStorable> xStore(xChild.is() ? getDataSourceOrModel(xChild->getParent()) : Reference<XInterface>(),UNO_QUERY); 120 // check for the concrete type 121 if ( xStore.is() && !xStore->isReadonly() && ::std::find_if(_rFlavors.begin(),_rFlavors.end(),TAppSupportedSotFunctor(E_TABLE,sal_True)) != _rFlavors.end()) 122 return DND_ACTION_COPY; 123 } 124 } 125 126 return DND_ACTION_NONE; 127 } 128 // ----------------------------------------------------------------------------- 129 sal_Int8 SbaTableQueryBrowser::executeDrop( const ExecuteDropEvent& _rEvt ) 130 { 131 SvLBoxEntry* pHitEntry = m_pTreeView->getListBox().GetEntry( _rEvt.maPosPixel ); 132 EntryType eEntryType = getEntryType( pHitEntry ); 133 if (!isContainer(eEntryType)) 134 { 135 DBG_ERROR("SbaTableQueryBrowser::executeDrop: what the hell did queryDrop do?"); 136 // queryDrop shoud not have allowed us to reach this situation .... 137 return DND_ACTION_NONE; 138 } 139 // a TransferableDataHelper for accessing the dropped data 140 TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable); 141 142 143 // reset the data of the previous async drop (if any) 144 if ( m_nAsyncDrop ) 145 Application::RemoveUserEvent(m_nAsyncDrop); 146 147 148 m_nAsyncDrop = 0; 149 m_aAsyncDrop.aDroppedData.clear(); 150 m_aAsyncDrop.nType = E_TABLE; 151 m_aAsyncDrop.nAction = _rEvt.mnAction; 152 m_aAsyncDrop.bError = sal_False; 153 m_aAsyncDrop.bHtml = sal_False; 154 m_aAsyncDrop.pDroppedAt = NULL; 155 m_aAsyncDrop.aUrl = ::rtl::OUString(); 156 157 158 // loop through the available formats and see what we can do ... 159 // first we have to check if it is our own format, if not we have to copy the stream :-( 160 if ( ODataAccessObjectTransferable::canExtractObjectDescriptor(aDroppedData.GetDataFlavorExVector()) ) 161 { 162 m_aAsyncDrop.aDroppedData = ODataAccessObjectTransferable::extractObjectDescriptor(aDroppedData); 163 m_aAsyncDrop.pDroppedAt = pHitEntry; 164 165 // asyncron because we some dialogs and we aren't allowed to show them while in D&D 166 m_nAsyncDrop = Application::PostUserEvent(LINK(this, SbaTableQueryBrowser, OnAsyncDrop)); 167 return DND_ACTION_COPY; 168 } 169 else 170 { 171 SharedConnection xDestConnection; 172 if ( ensureConnection( pHitEntry, xDestConnection ) 173 && xDestConnection.is() 174 && m_aTableCopyHelper.copyTagTable( aDroppedData, m_aAsyncDrop, xDestConnection ) 175 ) 176 { 177 m_aAsyncDrop.pDroppedAt = pHitEntry; 178 179 // asyncron because we some dialogs and we aren't allowed to show them while in D&D 180 m_nAsyncDrop = Application::PostUserEvent(LINK(this, SbaTableQueryBrowser, OnAsyncDrop)); 181 return DND_ACTION_COPY; 182 } 183 } 184 185 return DND_ACTION_NONE; 186 } 187 188 // ----------------------------------------------------------------------------- 189 sal_Bool SbaTableQueryBrowser::requestDrag( sal_Int8 /*_nAction*/, const Point& _rPosPixel ) 190 { 191 // get the affected list entry 192 // ensure that the entry which the user clicked at is selected 193 SvLBoxEntry* pHitEntry = m_pTreeView->getListBox().GetEntry( _rPosPixel ); 194 if (!pHitEntry) 195 // no drag of no entry was hit .... 196 return sal_False; 197 198 // it must be a query/table 199 EntryType eEntryType = getEntryType( pHitEntry ); 200 if (!isObject(eEntryType)) 201 return DND_ACTION_NONE; 202 203 TransferableHelper* pTransfer = implCopyObject( pHitEntry, ( etTableOrView == eEntryType ) ? CommandType::TABLE : CommandType::QUERY); 204 Reference< XTransferable> xEnsureDelete = pTransfer; 205 206 if (pTransfer) 207 pTransfer->StartDrag( &m_pTreeView->getListBox(), DND_ACTION_COPY ); 208 209 return NULL != pTransfer; 210 } 211 // ----------------------------------------------------------------------------- 212 IMPL_LINK(SbaTableQueryBrowser, OnCopyEntry, void*, /*NOTINTERESIN*/) 213 { 214 SvLBoxEntry* pSelected = m_pTreeView->getListBox().FirstSelected(); 215 if( isEntryCopyAllowed( pSelected ) ) 216 copyEntry( pSelected ); 217 return 0; 218 } 219 // ----------------------------------------------------------------------------- 220 sal_Bool SbaTableQueryBrowser::isEntryCopyAllowed(SvLBoxEntry* _pEntry) const 221 { 222 EntryType eType = getEntryType(_pEntry); 223 return ( eType == etTableOrView || eType == etQuery ); 224 } 225 // ----------------------------------------------------------------------------- 226 void SbaTableQueryBrowser::copyEntry(SvLBoxEntry* _pEntry) 227 { 228 TransferableHelper* pTransfer = NULL; 229 Reference< XTransferable> aEnsureDelete; 230 EntryType eType = getEntryType(_pEntry); 231 pTransfer = implCopyObject( _pEntry, eType == etQuery ? CommandType::QUERY : CommandType::TABLE); 232 aEnsureDelete = pTransfer; 233 if (pTransfer) 234 pTransfer->CopyToClipboard(getView()); 235 } 236 // ----------------------------------------------------------------------------- 237 IMPL_LINK( SbaTableQueryBrowser, OnAsyncDrop, void*, /*NOTINTERESTEDIN*/ ) 238 { 239 m_nAsyncDrop = 0; 240 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 241 ::osl::MutexGuard aGuard( getMutex() ); 242 243 if ( m_aAsyncDrop.nType == E_TABLE ) 244 { 245 SharedConnection xDestConnection; 246 if ( ensureConnection( m_aAsyncDrop.pDroppedAt, xDestConnection ) && xDestConnection.is() ) 247 { 248 SvLBoxEntry* pDataSourceEntry = m_pTreeView->getListBox().GetRootLevelParent(m_aAsyncDrop.pDroppedAt); 249 m_aTableCopyHelper.asyncCopyTagTable( m_aAsyncDrop, getDataSourceAcessor( pDataSourceEntry ), xDestConnection ); 250 } 251 } 252 253 m_aAsyncDrop.aDroppedData.clear(); 254 255 return 0L; 256 } 257 // ----------------------------------------------------------------------------- 258 void SbaTableQueryBrowser::clearTreeModel() 259 { 260 if (m_pTreeModel) 261 { 262 // clear the user data of the tree model 263 SvLBoxEntry* pEntryLoop = m_pTreeModel->First(); 264 while (pEntryLoop) 265 { 266 DBTreeListUserData* pData = static_cast<DBTreeListUserData*>(pEntryLoop->GetUserData()); 267 if(pData) 268 { 269 pEntryLoop->SetUserData(NULL); 270 Reference< XContainer > xContainer(pData->xContainer, UNO_QUERY); 271 if (xContainer.is()) 272 xContainer->removeContainerListener(this); 273 274 if ( pData->xConnection.is() ) 275 { 276 DBG_ASSERT( impl_isDataSourceEntry( pEntryLoop ), "SbaTableQueryBrowser::clearTreeModel: no data source entry, but a connection?" ); 277 // connections are to be stored *only* at the data source entries 278 impl_releaseConnection( pData->xConnection ); 279 } 280 281 delete pData; 282 } 283 pEntryLoop = m_pTreeModel->Next(pEntryLoop); 284 } 285 } 286 m_pCurrentlyDisplayed = NULL; 287 } 288 // ......................................................................... 289 } // namespace dbaui 290 // ......................................................................... 291 292