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