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 "AppController.hxx"
21 : #include <comphelper/sequence.hxx>
22 : #include <comphelper/property.hxx>
23 : #include <comphelper/processfactory.hxx>
24 : #include "dbustrings.hrc"
25 : #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
26 : #include <com/sun/star/sdbcx/XAppend.hpp>
27 : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
28 : #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
29 : #include <com/sun/star/container/XNameContainer.hpp>
30 : #include <com/sun/star/uno/XNamingService.hpp>
31 : #include <com/sun/star/sdbc/XDataSource.hpp>
32 : #include <com/sun/star/frame/XStorable.hpp>
33 : #include <com/sun/star/container/XChild.hpp>
34 : #include <com/sun/star/container/XHierarchicalNameContainer.hpp>
35 : #include <com/sun/star/sdbc/DataType.hpp>
36 : #include <com/sun/star/sdb/CommandType.hpp>
37 : #include <com/sun/star/sdb/XBookmarksSupplier.hpp>
38 : #include <com/sun/star/sdb/SQLContext.hpp>
39 : #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
40 : #include <com/sun/star/sdbcx/XViewsSupplier.hpp>
41 : #include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
42 : #include <com/sun/star/sdbcx/XDrop.hpp>
43 : #include <unotools/ucbhelper.hxx>
44 : #include "dlgsave.hxx"
45 : #include <comphelper/types.hxx>
46 : #include <vcl/layout.hxx>
47 : #include <cppuhelper/typeprovider.hxx>
48 : #include <cppuhelper/exc_hlp.hxx>
49 : #include <connectivity/dbexception.hxx>
50 : #include <vcl/waitobj.hxx>
51 : #include <rtl/ustrbuf.hxx>
52 : #include "AppView.hxx"
53 : #include <svx/dataaccessdescriptor.hxx>
54 : #include <svx/dbaobjectex.hxx>
55 : #include "browserids.hxx"
56 : #include "dbu_reghelper.hxx"
57 : #include "dbu_app.hrc"
58 : #include <vcl/menu.hxx>
59 : #include <comphelper/uno3.hxx>
60 : #include <vcl/svapp.hxx>
61 : #include <svtools/svlbitm.hxx>
62 : #include "listviewitems.hxx"
63 : #include "AppDetailView.hxx"
64 : #include "linkeddocuments.hxx"
65 : #include <vcl/lstbox.hxx>
66 : #include <connectivity/dbtools.hxx>
67 : #include "sqlmessage.hxx"
68 : #include "dbexchange.hxx"
69 : #include "UITools.hxx"
70 : #include <algorithm>
71 : #include <svtools/treelistbox.hxx>
72 : #include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
73 : #include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
74 : #include <unotools/pathoptions.hxx>
75 : #include <sfx2/docfilt.hxx>
76 : #include <svtools/fileview.hxx>
77 : #include <tools/diagnose_ex.h>
78 : #include <osl/diagnose.h>
79 : #include "defaultobjectnamecheck.hxx"
80 : #include <osl/mutex.hxx>
81 : #include "subcomponentmanager.hxx"
82 :
83 : namespace dbaui
84 : {
85 : using namespace ::dbtools;
86 : using namespace ::svx;
87 : using namespace ::svtools;
88 : using namespace ::com::sun::star::uno;
89 : using namespace ::com::sun::star::task;
90 : using namespace ::com::sun::star::beans;
91 : using namespace ::com::sun::star::lang;
92 : using namespace ::com::sun::star::container;
93 : using namespace ::com::sun::star::sdb;
94 : using namespace ::com::sun::star::sdbc;
95 : using namespace ::com::sun::star::sdbcx;
96 : using namespace ::com::sun::star::frame;
97 : using namespace ::com::sun::star::ucb;
98 : using namespace ::com::sun::star::util;
99 :
100 0 : void OApplicationController::deleteTables(const ::std::vector< OUString>& _rList)
101 : {
102 0 : SharedConnection xConnection( ensureConnection() );
103 :
104 0 : Reference<XTablesSupplier> xSup(xConnection,UNO_QUERY);
105 : OSL_ENSURE(xSup.is(),"OApplicationController::deleteTable: no XTablesSuppier!");
106 0 : if ( xSup.is() )
107 : {
108 0 : Reference<XNameAccess> xTables = xSup->getTables();
109 0 : Reference<XDrop> xDrop(xTables,UNO_QUERY);
110 0 : if ( xDrop.is() )
111 : {
112 0 : bool bConfirm = true;
113 0 : ::std::vector< OUString>::const_iterator aEnd = _rList.end();
114 0 : for (::std::vector< OUString>::const_iterator aIter = _rList.begin(); aIter != aEnd; ++aIter)
115 : {
116 0 : OUString sTableName = *aIter;
117 :
118 0 : sal_Int32 nResult = RET_YES;
119 0 : if ( bConfirm )
120 0 : nResult = ::dbaui::askForUserAction(getView(),STR_TITLE_CONFIRM_DELETION ,STR_QUERY_DELETE_TABLE,_rList.size() > 1 && (aIter+1) != _rList.end(),sTableName);
121 :
122 : bool bUserConfirmedDelete =
123 : ( RET_YES == nResult )
124 0 : || ( RET_ALL == nResult );
125 0 : if ( bUserConfirmedDelete && m_pSubComponentManager->closeSubFrames( sTableName, E_TABLE ) )
126 : {
127 0 : SQLExceptionInfo aErrorInfo;
128 : try
129 : {
130 0 : if ( xTables->hasByName(sTableName) )
131 0 : xDrop->dropByName(sTableName);
132 : else
133 : {// could be a view
134 0 : Reference<XViewsSupplier> xViewsSup(xConnection,UNO_QUERY);
135 :
136 0 : Reference<XNameAccess> xViews;
137 0 : if ( xViewsSup.is() )
138 : {
139 0 : xViews = xViewsSup->getViews();
140 0 : if ( xViews.is() && xViews->hasByName(sTableName) )
141 : {
142 0 : xDrop.set(xViews,UNO_QUERY);
143 0 : if ( xDrop.is() )
144 0 : xDrop->dropByName(sTableName);
145 : }
146 0 : }
147 : }
148 : }
149 0 : catch(SQLContext& e) { aErrorInfo = e; }
150 0 : catch(SQLWarning& e) { aErrorInfo = e; }
151 0 : catch(SQLException& e) { aErrorInfo = e; }
152 0 : catch(WrappedTargetException& e)
153 : {
154 0 : SQLException aSql;
155 0 : if(e.TargetException >>= aSql)
156 0 : aErrorInfo = aSql;
157 : else
158 0 : OSL_FAIL("OApplicationController::implDropTable: something strange happened!");
159 : }
160 0 : catch( const Exception& )
161 : {
162 : DBG_UNHANDLED_EXCEPTION();
163 : }
164 :
165 0 : if ( aErrorInfo.isValid() )
166 0 : showError(aErrorInfo);
167 :
168 0 : if ( RET_ALL == nResult )
169 0 : bConfirm = false;
170 : }
171 : else
172 0 : break;
173 0 : }
174 : }
175 : else
176 : {
177 0 : OUString sMessage(ModuleRes(STR_MISSING_TABLES_XDROP));
178 0 : ScopedVclPtrInstance< MessageDialog > aError(getView(), sMessage);
179 0 : aError->Execute();
180 0 : }
181 0 : }
182 0 : }
183 :
184 0 : void OApplicationController::deleteObjects( ElementType _eType, const ::std::vector< OUString>& _rList, bool _bConfirm )
185 : {
186 0 : Reference< XNameContainer > xNames( getElements( _eType ), UNO_QUERY );
187 0 : Reference< XHierarchicalNameContainer > xHierarchyName( xNames, UNO_QUERY );
188 0 : if ( xNames.is() )
189 : {
190 0 : OString sDialogPosition;
191 0 : short eResult = _bConfirm ? svtools::QUERYDELETE_YES : svtools::QUERYDELETE_ALL;
192 :
193 : // The list of elements to delete is allowed to contain related elements: A given element may
194 : // be the ancestor or child of another element from the list.
195 : // We want to ensure that ancestors get deleted first, so we normalize the list in this respect.
196 : // #i33353#
197 0 : ::std::set< OUString > aDeleteNames;
198 : // Note that this implicitly uses ::std::less< OUString > a comparison operation, which
199 : // results in lexicographical order, which is exactly what we need, because "foo" is *before*
200 : // any "foo/bar" in this order.
201 : ::std::copy(
202 : _rList.begin(), _rList.end(),
203 : ::std::insert_iterator< ::std::set< OUString > >( aDeleteNames, aDeleteNames.begin() )
204 0 : );
205 :
206 0 : ::std::set< OUString >::size_type nCount = aDeleteNames.size();
207 0 : for ( ::std::set< OUString >::size_type nObjectsLeft = nCount; !aDeleteNames.empty(); )
208 : {
209 0 : ::std::set< OUString >::iterator aThisRound = aDeleteNames.begin();
210 :
211 0 : if ( eResult != svtools::QUERYDELETE_ALL )
212 : {
213 0 : ScopedVclPtrInstance< svtools::QueryDeleteDlg_Impl > aDlg(getView(), *aThisRound);
214 :
215 0 : if ( !sDialogPosition.isEmpty() )
216 0 : aDlg->SetWindowState( sDialogPosition );
217 :
218 0 : if ( nObjectsLeft > 1 )
219 0 : aDlg->EnableAllButton();
220 :
221 0 : eResult = aDlg->Execute();
222 0 : if (eResult == svtools::QUERYDELETE_CANCEL)
223 0 : return;
224 :
225 0 : sDialogPosition = aDlg->GetWindowState( );
226 : }
227 :
228 0 : bool bSuccess = false;
229 :
230 : bool bUserConfirmedDelete =
231 : ( eResult == svtools::QUERYDELETE_ALL )
232 0 : || ( eResult == svtools::QUERYDELETE_YES );
233 :
234 0 : if ( bUserConfirmedDelete
235 0 : && ( _eType != E_QUERY || m_pSubComponentManager->closeSubFrames( *aThisRound, _eType ) )
236 : )
237 : {
238 : try
239 : {
240 0 : if ( xHierarchyName.is() )
241 0 : xHierarchyName->removeByHierarchicalName( *aThisRound );
242 : else
243 0 : xNames->removeByName( *aThisRound );
244 :
245 0 : bSuccess = true;
246 :
247 : // now that we removed the element, care for all its child elements
248 : // which may also be a part of the list
249 : // #i33353#
250 : OSL_ENSURE( aThisRound->getLength() - 1 >= 0, "OApplicationController::deleteObjects: empty name?" );
251 0 : OUStringBuffer sSmallestSiblingName( *aThisRound );
252 0 : sSmallestSiblingName.append( (sal_Unicode)( '/' + 1) );
253 :
254 0 : ::std::set< OUString >::iterator aUpperChildrenBound = aDeleteNames.lower_bound( sSmallestSiblingName.makeStringAndClear() );
255 0 : for ( ::std::set< OUString >::iterator aObsolete = aThisRound;
256 : aObsolete != aUpperChildrenBound;
257 : )
258 : {
259 0 : ::std::set< OUString >::iterator aNextObsolete = aObsolete; ++aNextObsolete;
260 0 : aDeleteNames.erase( aObsolete );
261 0 : --nObjectsLeft;
262 0 : aObsolete = aNextObsolete;
263 0 : }
264 : }
265 0 : catch(const SQLException&)
266 : {
267 0 : showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
268 : }
269 0 : catch(const WrappedTargetException& e)
270 : {
271 0 : SQLException aSql;
272 0 : if ( e.TargetException >>= aSql )
273 0 : showError( SQLExceptionInfo( e.TargetException ) );
274 : else
275 0 : OSL_FAIL( "OApplicationController::deleteObjects: something strange happened!" );
276 : }
277 0 : catch( const Exception& )
278 : {
279 : DBG_UNHANDLED_EXCEPTION();
280 : }
281 : }
282 :
283 0 : if ( !bSuccess )
284 : {
285 : // okay, this object could not be deleted (or the user did not want to delete it),
286 : // but continue with the rest
287 0 : aDeleteNames.erase( aThisRound );
288 0 : --nObjectsLeft;
289 : }
290 0 : }
291 0 : }
292 : }
293 :
294 0 : void OApplicationController::deleteEntries()
295 : {
296 0 : SolarMutexGuard aSolarGuard;
297 0 : ::osl::MutexGuard aGuard( getMutex() );
298 :
299 0 : if ( getContainer() )
300 : {
301 0 : ::std::vector< OUString> aList;
302 0 : getSelectionElementNames(aList);
303 0 : ElementType eType = getContainer()->getElementType();
304 0 : switch(eType)
305 : {
306 : case E_TABLE:
307 0 : deleteTables(aList);
308 0 : break;
309 : case E_QUERY:
310 0 : deleteObjects( E_QUERY, aList, true );
311 0 : break;
312 : case E_FORM:
313 0 : deleteObjects( E_FORM, aList, true );
314 0 : break;
315 : case E_REPORT:
316 0 : deleteObjects( E_REPORT, aList, true );
317 0 : break;
318 : case E_NONE:
319 0 : break;
320 0 : }
321 0 : }
322 0 : }
323 :
324 : // DO NOT CALL with getMutex() held!!
325 0 : const SharedConnection& OApplicationController::ensureConnection( ::dbtools::SQLExceptionInfo* _pErrorInfo )
326 : {
327 :
328 : // This looks like double checked locking, but it is not,
329 : // because every access (read *or* write) to m_xDataSourceConnection
330 : // is mutexed.
331 : // See http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
332 : // for what I'm referring to.
333 : // We cannot use the TLS (thread-local storage) solution
334 : // since support for TLS is not up to the snuff on Windows :-(
335 :
336 : {
337 0 : ::osl::MutexGuard aGuard( getMutex() );
338 :
339 0 : if ( m_xDataSourceConnection.is() )
340 0 : return m_xDataSourceConnection;
341 : }
342 :
343 0 : WaitObject aWO(getView());
344 0 : Reference<XConnection> conn;
345 : {
346 0 : SolarMutexGuard aSolarGuard;
347 :
348 0 : OUString sConnectingContext( ModuleRes( STR_COULDNOTCONNECT_DATASOURCE ) );
349 0 : sConnectingContext = sConnectingContext.replaceFirst("$name$", getStrippedDatabaseName());
350 :
351 : // do the connection *without* holding getMutex() to avoid deadlock
352 : // when we are not in the main thread and we need username/password
353 : // (and thus to display a dialog, which will be done by the main thread)
354 : // and there is an event that needs getMutex() *before* us in the main thread's queue
355 : // See fdo#63391
356 0 : conn.set( connect( getDatabaseName(), sConnectingContext, _pErrorInfo ) );
357 : }
358 :
359 0 : if (conn.is())
360 : {
361 0 : ::osl::MutexGuard aGuard( getMutex() );
362 0 : if ( m_xDataSourceConnection.is() )
363 : {
364 0 : Reference< XComponent > comp (conn, UNO_QUERY);
365 0 : if(comp.is())
366 : {
367 : try
368 : {
369 0 : comp->dispose();
370 : }
371 0 : catch( const Exception& )
372 : {
373 : OSL_FAIL( "dbaui::OApplicationController::ensureConnection could not dispose of temporary unused connection" );
374 : }
375 : }
376 0 : conn.clear();
377 : }
378 : else
379 : {
380 0 : m_xDataSourceConnection.reset(conn);
381 0 : SQLExceptionInfo aError;
382 : try
383 : {
384 0 : m_xMetaData = m_xDataSourceConnection->getMetaData();
385 : }
386 0 : catch( const SQLException& )
387 : {
388 0 : aError = ::cppu::getCaughtException();
389 : }
390 0 : catch( const Exception& )
391 : {
392 : DBG_UNHANDLED_EXCEPTION();
393 : }
394 0 : if ( aError.isValid() )
395 : {
396 0 : if ( _pErrorInfo )
397 : {
398 0 : *_pErrorInfo = aError;
399 : }
400 : else
401 : {
402 0 : SolarMutexGuard aSolarGuard;
403 0 : showError( aError );
404 : }
405 0 : }
406 0 : }
407 : }
408 :
409 0 : return m_xDataSourceConnection;
410 : }
411 :
412 251 : bool OApplicationController::isDataSourceReadOnly() const
413 : {
414 251 : Reference<XStorable> xStore(m_xModel,UNO_QUERY);
415 251 : return !xStore.is() || xStore->isReadonly();
416 : }
417 :
418 27 : bool OApplicationController::isConnectionReadOnly() const
419 : {
420 27 : bool bIsConnectionReadOnly = true;
421 27 : if ( m_xMetaData.is() )
422 : {
423 : try
424 : {
425 0 : bIsConnectionReadOnly = m_xMetaData->isReadOnly();
426 : }
427 0 : catch(const SQLException&)
428 : {
429 : DBG_UNHANDLED_EXCEPTION();
430 : }
431 : }
432 : // TODO check configuration
433 27 : return bIsConnectionReadOnly;
434 : }
435 :
436 3 : Reference< XNameAccess > OApplicationController::getElements( ElementType _eType )
437 : {
438 3 : Reference< XNameAccess > xElements;
439 : try
440 : {
441 3 : switch ( _eType )
442 : {
443 : case E_REPORT:
444 : {
445 0 : Reference< XReportDocumentsSupplier > xSupp( m_xModel, UNO_QUERY_THROW );
446 0 : xElements.set( xSupp->getReportDocuments(), UNO_SET_THROW );
447 : }
448 0 : break;
449 :
450 : case E_FORM:
451 : {
452 3 : Reference< XFormDocumentsSupplier > xSupp( m_xModel, UNO_QUERY_THROW );
453 3 : xElements.set( xSupp->getFormDocuments(), UNO_SET_THROW );
454 : }
455 3 : break;
456 :
457 : case E_QUERY:
458 : {
459 0 : xElements.set( getQueryDefinitions(), UNO_QUERY_THROW );
460 : }
461 0 : break;
462 :
463 : case E_TABLE:
464 : {
465 0 : if ( m_xDataSourceConnection.is() )
466 : {
467 0 : Reference< XTablesSupplier > xSup( getConnection(), UNO_QUERY_THROW );
468 0 : xElements.set( xSup->getTables(), UNO_SET_THROW );
469 : }
470 : }
471 0 : break;
472 :
473 : default:
474 0 : break;
475 : }
476 : }
477 0 : catch(const Exception&)
478 : {
479 : DBG_UNHANDLED_EXCEPTION();
480 : }
481 :
482 3 : return xElements;
483 : }
484 :
485 0 : void OApplicationController::getSelectionElementNames(::std::vector< OUString>& _rNames) const
486 : {
487 0 : SolarMutexGuard aSolarGuard;
488 0 : ::osl::MutexGuard aGuard( getMutex() );
489 :
490 : OSL_ENSURE(getContainer(),"View isn't valid! -> GPF");
491 :
492 0 : getContainer()->getSelectionElementNames( _rNames );
493 0 : }
494 :
495 0 : ::std::unique_ptr< OLinkedDocumentsAccess > OApplicationController::getDocumentsAccess( ElementType _eType )
496 : {
497 : OSL_ENSURE( ( _eType == E_TABLE ) || ( _eType == E_QUERY ) || ( _eType == E_FORM ) || ( _eType == E_REPORT ),
498 : "OApplicationController::getDocumentsAccess: only forms and reports are supported here!" );
499 :
500 0 : SharedConnection xConnection( ensureConnection() );
501 0 : Reference< XNameAccess > xDocContainer;
502 :
503 0 : if ( ( _eType == E_FORM ) || ( _eType == E_REPORT ) )
504 : {
505 0 : xDocContainer.set( getElements( _eType ) );
506 : OSL_ENSURE( xDocContainer.is(), "OApplicationController::getDocumentsAccess: invalid container!" );
507 : }
508 :
509 : ::std::unique_ptr< OLinkedDocumentsAccess > pDocuments( new OLinkedDocumentsAccess(
510 0 : getView(), this, getORB(), xDocContainer, xConnection, getDatabaseName()
511 0 : ) );
512 0 : return pDocuments;
513 : }
514 :
515 0 : TransferableHelper* OApplicationController::copyObject()
516 : {
517 : try
518 : {
519 0 : SolarMutexGuard aSolarGuard;
520 0 : ::osl::MutexGuard aGuard( getMutex() );
521 :
522 0 : ElementType eType = getContainer()->getElementType();
523 0 : TransferableHelper* pData = NULL;
524 0 : switch( eType )
525 : {
526 : case E_TABLE:
527 : case E_QUERY:
528 : {
529 0 : SharedConnection xConnection( ensureConnection() );
530 0 : Reference< XDatabaseMetaData> xMetaData;
531 0 : if ( xConnection.is() )
532 0 : xMetaData = xConnection->getMetaData();
533 :
534 0 : OUString sName = getContainer()->getQualifiedName( NULL );
535 0 : if ( !sName.isEmpty() )
536 : {
537 0 : OUString sDataSource = getDatabaseName();
538 :
539 0 : if ( eType == E_TABLE )
540 : {
541 0 : pData = new ODataClipboard(sDataSource, CommandType::TABLE, sName, xConnection, getNumberFormatter(xConnection, getORB()), getORB());
542 : }
543 : else
544 : {
545 0 : pData = new ODataClipboard(sDataSource, CommandType::QUERY, sName, getNumberFormatter(xConnection, getORB()), getORB());
546 0 : }
547 0 : }
548 : }
549 0 : break;
550 : case E_FORM:
551 : case E_REPORT:
552 : {
553 0 : ::std::vector< OUString> aList;
554 0 : getSelectionElementNames(aList);
555 0 : Reference< XHierarchicalNameAccess > xElements(getElements(eType),UNO_QUERY);
556 0 : if ( xElements.is() && !aList.empty() )
557 : {
558 0 : Reference< XContent> xContent(xElements->getByHierarchicalName(*aList.begin()),UNO_QUERY);
559 0 : pData = new OComponentTransferable( getDatabaseName(), xContent );
560 0 : }
561 : }
562 0 : break;
563 : default:
564 0 : break;
565 : }
566 :
567 : // the ownership goes to ODataClipboards
568 0 : return pData;
569 : }
570 0 : catch(const SQLException&)
571 : {
572 0 : showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
573 : }
574 0 : catch( const Exception& )
575 : {
576 : DBG_UNHANDLED_EXCEPTION();
577 : }
578 0 : return NULL;
579 : }
580 :
581 0 : bool OApplicationController::paste( ElementType _eType, const svx::ODataAccessDescriptor& _rPasteData, const OUString& _sParentFolder, bool _bMove)
582 : {
583 : try
584 : {
585 0 : if ( _eType == E_QUERY )
586 : {
587 0 : sal_Int32 nCommandType = CommandType::TABLE;
588 0 : if ( _rPasteData.has(daCommandType) )
589 0 : _rPasteData[daCommandType] >>= nCommandType;
590 :
591 0 : if ( CommandType::QUERY == nCommandType || CommandType::COMMAND == nCommandType )
592 : {
593 : // read all necessary data
594 :
595 0 : OUString sCommand;
596 0 : bool bEscapeProcessing = true;
597 :
598 0 : _rPasteData[daCommand] >>= sCommand;
599 0 : if ( _rPasteData.has(daEscapeProcessing) )
600 0 : _rPasteData[daEscapeProcessing] >>= bEscapeProcessing;
601 :
602 : // plausibility check
603 0 : bool bValidDescriptor = false;
604 0 : OUString sDataSourceName = _rPasteData.getDataSource();
605 0 : if (CommandType::QUERY == nCommandType)
606 0 : bValidDescriptor = sDataSourceName.getLength() && sCommand.getLength();
607 0 : else if (CommandType::COMMAND == nCommandType)
608 0 : bValidDescriptor = !sCommand.isEmpty();
609 0 : if (!bValidDescriptor)
610 : {
611 : OSL_FAIL("OApplicationController::paste: invalid descriptor!");
612 0 : return false;
613 : }
614 :
615 : // the target object name (as we'll suggest it to the user)
616 0 : OUString sTargetName;
617 : try
618 : {
619 0 : if ( CommandType::QUERY == nCommandType )
620 0 : sTargetName = sCommand;
621 :
622 0 : if ( sTargetName.isEmpty() )
623 : {
624 0 : OUString sDefaultName = OUString( ModuleRes( STR_QRY_TITLE ) );
625 0 : sDefaultName = sDefaultName.getToken( 0, ' ' );
626 :
627 0 : Reference< XNameAccess > xQueries( getQueryDefinitions(), UNO_QUERY_THROW );
628 0 : sTargetName = ::dbtools::createUniqueName( xQueries, sDefaultName, false );
629 : }
630 : }
631 0 : catch(const Exception&)
632 : {
633 : DBG_UNHANDLED_EXCEPTION();
634 : }
635 :
636 0 : Reference< XPropertySet > xQuery;
637 0 : if (CommandType::QUERY == nCommandType)
638 : {
639 : // need to extract the statement and the escape processing flag from the query object
640 0 : bool bSuccess = false;
641 : try
642 : {
643 : // the concrete query
644 : Reference< XQueryDefinitionsSupplier > xSourceQuerySup(
645 0 : getDataSourceByName( sDataSourceName, getView(), getORB(), NULL ),
646 0 : UNO_QUERY_THROW );
647 0 : Reference< XNameAccess > xQueries( xSourceQuerySup->getQueryDefinitions(), UNO_SET_THROW );
648 0 : if ( xQueries->hasByName( sCommand ) )
649 : {
650 0 : xQuery.set( xQueries->getByName(sCommand), UNO_QUERY_THROW );
651 0 : bSuccess = true;
652 0 : }
653 : }
654 0 : catch(SQLException&) { throw; } // caught and handled by the outer catch
655 0 : catch( const Exception& )
656 : {
657 : DBG_UNHANDLED_EXCEPTION();
658 : }
659 :
660 0 : if (!bSuccess)
661 : {
662 : OSL_FAIL("OApplicationController::paste: could not extract the source query object!");
663 : // TODO: maybe this is worth an error message to be displayed to the user ....
664 0 : return false;
665 : }
666 : }
667 :
668 0 : Reference< XNameContainer > xDestQueries(getQueryDefinitions(), UNO_QUERY);
669 0 : Reference< XSingleServiceFactory > xQueryFactory(xDestQueries, UNO_QUERY);
670 0 : if (!xQueryFactory.is())
671 : {
672 : OSL_FAIL("OApplicationController::paste: invalid destination query container!");
673 0 : return false;
674 : }
675 :
676 : // here we have everything needed to create a new query object ...
677 : // ... ehm, except a new name
678 0 : ensureConnection();
679 :
680 0 : DynamicTableOrQueryNameCheck aNameChecker( getConnection(), CommandType::QUERY );
681 0 : ::dbtools::SQLExceptionInfo aDummy;
682 0 : bool bNeedAskForName = ( sCommand.isEmpty() )
683 : /* we did not have a source name, so the target name was auto-generated */
684 0 : || ( !aNameChecker.isNameValid( sTargetName, aDummy ) );
685 : /* name is invalid in the target DB (e.g. because it already
686 : has a /table/ with that name) */
687 0 : if ( bNeedAskForName )
688 : {
689 : ScopedVclPtrInstance<OSaveAsDlg> aAskForName(
690 0 : getView(),
691 : CommandType::QUERY,
692 : getORB(),
693 0 : getConnection(),
694 : sTargetName,
695 : aNameChecker,
696 0 : SAD_ADDITIONAL_DESCRIPTION | SAD_TITLE_PASTE_AS );
697 0 : if ( RET_OK != aAskForName->Execute() )
698 : // cancelled by the user
699 0 : return false;
700 0 : sTargetName = aAskForName->getName();
701 : }
702 :
703 : // create a new object
704 0 : Reference< XPropertySet > xNewQuery(xQueryFactory->createInstance(), UNO_QUERY);
705 : OSL_ENSURE(xNewQuery.is(), "OApplicationController::paste: invalid object created by factory!");
706 0 : if (xNewQuery.is())
707 : {
708 : // initialize
709 0 : if ( xQuery.is() )
710 0 : ::comphelper::copyProperties(xQuery,xNewQuery);
711 : else
712 : {
713 0 : xNewQuery->setPropertyValue(PROPERTY_COMMAND,makeAny(sCommand));
714 0 : xNewQuery->setPropertyValue(PROPERTY_ESCAPE_PROCESSING,makeAny(bEscapeProcessing));
715 : }
716 : // insert
717 0 : xDestQueries->insertByName( sTargetName, makeAny(xNewQuery) );
718 0 : xNewQuery.set(xDestQueries->getByName( sTargetName),UNO_QUERY);
719 0 : if ( xQuery.is() && xNewQuery.is() )
720 : {
721 0 : Reference<XColumnsSupplier> xSrcColSup(xQuery,UNO_QUERY);
722 0 : Reference<XColumnsSupplier> xDstColSup(xNewQuery,UNO_QUERY);
723 0 : if ( xSrcColSup.is() && xDstColSup.is() )
724 : {
725 0 : Reference<XNameAccess> xSrcNameAccess = xSrcColSup->getColumns();
726 0 : Reference<XNameAccess> xDstNameAccess = xDstColSup->getColumns();
727 0 : Reference<XDataDescriptorFactory> xFac(xDstNameAccess,UNO_QUERY);
728 0 : Reference<XAppend> xAppend(xFac,UNO_QUERY);
729 0 : if ( xSrcNameAccess.is() && xDstNameAccess.is() && xSrcNameAccess->hasElements() && xAppend.is() )
730 : {
731 0 : Reference<XPropertySet> xDstProp(xFac->createDataDescriptor());
732 :
733 0 : Sequence< OUString> aSeq = xSrcNameAccess->getElementNames();
734 0 : const OUString* pIter = aSeq.getConstArray();
735 0 : const OUString* pEnd = pIter + aSeq.getLength();
736 0 : for( ; pIter != pEnd ; ++pIter)
737 : {
738 0 : Reference<XPropertySet> xSrcProp(xSrcNameAccess->getByName(*pIter),UNO_QUERY);
739 0 : ::comphelper::copyProperties(xSrcProp,xDstProp);
740 0 : xAppend->appendByDescriptor(xDstProp);
741 0 : }
742 0 : }
743 0 : }
744 : }
745 0 : }
746 : }
747 : else
748 : OSL_TRACE("There should be a sequence in it!");
749 0 : return true;
750 : }
751 0 : else if ( _rPasteData.has(daComponent) ) // forms or reports
752 : {
753 0 : Reference<XContent> xContent;
754 0 : _rPasteData[daComponent] >>= xContent;
755 0 : return insertHierachyElement(_eType,_sParentFolder,Reference<XNameAccess>(xContent,UNO_QUERY).is(),xContent,_bMove);
756 : }
757 : }
758 0 : catch(const SQLException&) { showError( SQLExceptionInfo( ::cppu::getCaughtException() ) ); }
759 0 : catch(const Exception& )
760 : {
761 : DBG_UNHANDLED_EXCEPTION();
762 : }
763 0 : return false;
764 : }
765 :
766 0 : Reference<XNameContainer> OApplicationController::getQueryDefinitions() const
767 : {
768 0 : Reference<XQueryDefinitionsSupplier> xSet(m_xDataSource,UNO_QUERY);
769 0 : Reference<XNameContainer> xNames;
770 0 : if ( xSet.is() )
771 : {
772 0 : xNames.set(xSet->getQueryDefinitions(),UNO_QUERY);
773 : }
774 0 : return xNames;
775 : }
776 :
777 0 : void OApplicationController::getSupportedFormats(ElementType _eType,::std::vector<SotClipboardFormatId>& _rFormatIds)
778 : {
779 0 : switch( _eType )
780 : {
781 : case E_TABLE:
782 0 : _rFormatIds.push_back(SotClipboardFormatId::DBACCESS_TABLE);
783 0 : _rFormatIds.push_back(SotClipboardFormatId::RTF);
784 0 : _rFormatIds.push_back(SotClipboardFormatId::HTML);
785 : // run through
786 : case E_QUERY:
787 0 : _rFormatIds.push_back(SotClipboardFormatId::DBACCESS_QUERY);
788 0 : break;
789 : default:
790 0 : break;
791 : }
792 0 : }
793 :
794 0 : bool OApplicationController::isTableFormat() const
795 : {
796 0 : return OTableCopyHelper::isTableFormat(getViewClipboard());
797 : }
798 :
799 0 : IMPL_LINK_NOARG( OApplicationController, OnAsyncDrop )
800 : {
801 0 : m_nAsyncDrop = 0;
802 0 : SolarMutexGuard aSolarGuard;
803 0 : ::osl::MutexGuard aGuard( getMutex() );
804 :
805 0 : if ( m_aAsyncDrop.nType == E_TABLE )
806 : {
807 0 : SharedConnection xConnection( ensureConnection() );
808 0 : if ( xConnection.is() )
809 0 : m_aTableCopyHelper.asyncCopyTagTable( m_aAsyncDrop, getDatabaseName(), xConnection );
810 : }
811 : else
812 : {
813 0 : if ( paste(m_aAsyncDrop.nType,m_aAsyncDrop.aDroppedData,m_aAsyncDrop.aUrl,m_aAsyncDrop.nAction == DND_ACTION_MOVE)
814 0 : && m_aAsyncDrop.nAction == DND_ACTION_MOVE )
815 : {
816 0 : Reference<XContent> xContent;
817 0 : m_aAsyncDrop.aDroppedData[daComponent] >>= xContent;
818 0 : ::std::vector< OUString> aList;
819 0 : sal_Int32 nIndex = 0;
820 0 : OUString sName = xContent->getIdentifier()->getContentIdentifier();
821 0 : OUString sErase = sName.getToken(0,'/',nIndex); // we don't want to have the "private:forms" part
822 0 : if ( nIndex != -1 )
823 : {
824 0 : aList.push_back(sName.copy(sErase.getLength() + 1));
825 0 : deleteObjects( m_aAsyncDrop.nType, aList, false );
826 0 : }
827 : }
828 : }
829 :
830 0 : m_aAsyncDrop.aDroppedData.clear();
831 :
832 0 : return 0L;
833 : }
834 :
835 36 : } // namespace dbaui
836 :
837 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|