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 #ifndef _SFXSIDS_HRC
31 #include <sfx2/sfxsids.hrc>
32 #endif
33 #ifndef _DBU_QRY_HRC_
34 #include "dbu_qry.hrc"
35 #endif
36 #ifndef DBACCESS_UI_BROWSER_ID_HXX
37 #include "browserids.hxx"
38 #endif
39 #ifndef _COMPHELPER_TYPES_HXX_
40 #include <comphelper/types.hxx>
41 #endif
42 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
43 #include "dbustrings.hrc"
44 #endif
45 #ifndef _CONNECTIVITY_DBTOOLS_HXX_
46 #include <connectivity/dbtools.hxx>
47 #endif
48 #ifndef _COM_SUN_STAR_FRAME_FRAMESEARCHFLAG_HPP_
49 #include <com/sun/star/frame/FrameSearchFlag.hpp>
50 #endif
51 #ifndef _COMPHELPER_EXTRACT_HXX_
52 #include <comphelper/extract.hxx>
53 #endif
54 #ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
55 #include <com/sun/star/container/XChild.hpp>
56 #endif
57 #ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
58 #include <com/sun/star/container/XNameContainer.hpp>
59 #endif
60 #ifndef _COM_SUN_STAR_SDBCX_XDATADESCRIPTORFACTORY_HPP_
61 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
62 #endif
63 #ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_
64 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
65 #endif
66 #ifndef _COM_SUN_STAR_SDBCX_KEYTYPE_HPP_
67 #include <com/sun/star/sdbcx/KeyType.hpp>
68 #endif
69 #ifndef _COM_SUN_STAR_SDBCX_XDROP_HPP_
70 #include <com/sun/star/sdbcx/XDrop.hpp>
71 #endif
72 #ifndef _COM_SUN_STAR_SDBCX_XALTERTABLE_HPP_
73 #include <com/sun/star/sdbcx/XAlterTable.hpp>
74 #endif
75 #ifndef _COM_SUN_STAR_SDBCX_XAPPEND_HPP_
76 #include <com/sun/star/sdbcx/XAppend.hpp>
77 #endif
78 #ifndef _COM_SUN_STAR_SDB_SQLCONTEXT_HPP_
79 #include <com/sun/star/sdb/SQLContext.hpp>
80 #endif
81 #ifndef _COM_SUN_STAR_SDBC_SQLWARNING_HPP_
82 #include <com/sun/star/sdbc/SQLWarning.hpp>
83 #endif
84 #ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_
85 #include <com/sun/star/sdbc/ColumnValue.hpp>
86 #endif
87 #ifndef _COM_SUN_STAR_SDBC_XROW_HPP_
88 #include <com/sun/star/sdbc/XRow.hpp>
89 #endif
90 #ifndef _DBHELPER_DBEXCEPTION_HXX_
91 #include <connectivity/dbexception.hxx>
92 #endif
93 #ifndef _COM_SUN_STAR_UI_DIALOGS_XEXECUTABLEDIALOG_HPP_
94 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
95 #endif
96 #ifndef _COMPHELPER_STREAMSECTION_HXX_
97 #include <comphelper/streamsection.hxx>
98 #endif
99 #ifndef _COMPHELPER_BASIC_IO_HXX_
100 #include <comphelper/basicio.hxx>
101 #endif
102 #ifndef _COMPHELPER_SEQSTREAM_HXX
103 #include <comphelper/seqstream.hxx>
104 #endif
105 #ifndef _COM_SUN_STAR_IO_XACTIVEDATASOURCE_HPP_
106 #include <com/sun/star/io/XActiveDataSource.hpp>
107 #endif
108 #ifndef _COM_SUN_STAR_IO_XACTIVEDATASINK_HPP_
109 #include <com/sun/star/io/XActiveDataSink.hpp>
110 #endif
111 #ifndef _DBAUI_SQLMESSAGE_HXX_
112 #include "sqlmessage.hxx"
113 #endif
114 #ifndef DBAUI_JOINCONTROLLER_HXX
115 #include "JoinController.hxx"
116 #endif
117 #ifndef _SV_MSGBOX_HXX
118 #include <vcl/msgbox.hxx>
119 #endif
120 #ifndef DBAUI_TABLEWINDOWDATA_HXX
121 #include "TableWindowData.hxx"
122 #endif
123 #ifndef DBAUI_TABLEWINDOW_HXX
124 #include "TableWindow.hxx"
125 #endif
126 #ifndef DBAUI_TABLECONNECTIONDATA_HXX
127 #include "TableConnectionData.hxx"
128 #endif
129 #ifndef DBAUI_QYDLGTAB_HXX
130 #include "adtabdlg.hxx"
131 #endif
132 #ifndef _SV_WAITOBJ_HXX
133 #include <vcl/waitobj.hxx>
134 #endif
135 #ifndef _SV_SVAPP_HXX
136 #include <vcl/svapp.hxx>
137 #endif
138 #ifndef _VOS_MUTEX_HXX_
139 #include <vos/mutex.hxx>
140 #endif
141 #ifndef DBAUI_TOOLS_HXX
142 #include "UITools.hxx"
143 #endif
144 
145 #include <boost/optional.hpp>
146 
147 using namespace ::com::sun::star::uno;
148 using namespace ::com::sun::star::io;
149 using namespace ::com::sun::star::beans;
150 using namespace ::com::sun::star::frame;
151 using namespace ::com::sun::star::util;
152 using namespace ::com::sun::star::lang;
153 using namespace ::com::sun::star::container;
154 using namespace ::com::sun::star::sdbcx;
155 using namespace ::com::sun::star::sdbc;
156 using namespace ::com::sun::star::sdb;
157 using namespace ::com::sun::star::ui::dialogs;
158 using namespace ::dbtools;
159 using namespace ::comphelper;
160 
161 // .............................................................................
162 namespace dbaui
163 {
164 // .............................................................................
165 
166 // =============================================================================
167 // = AddTableDialogContext
168 // =============================================================================
169 class AddTableDialogContext : public IAddTableDialogContext
170 {
171     OJoinController& m_rController;
172 
173 public:
174     AddTableDialogContext( OJoinController& _rController )
175         :m_rController( _rController )
176     {
177     }
178 
179     // IAddTableDialogContext
180     virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >
181                     getConnection() const;
182     virtual bool    allowViews() const;
183     virtual bool    allowQueries() const;
184     virtual bool    allowAddition() const;
185     virtual void    addTableWindow( const String& _rQualifiedTableName, const String& _rAliasName );
186     virtual void    onWindowClosing( const Window* _pWindow );
187 
188 private:
189     OJoinTableView* getTableView() const;
190 };
191 
192 // -----------------------------------------------------------------------------
193 Reference< XConnection > AddTableDialogContext::getConnection() const
194 {
195     return m_rController.getConnection();
196 }
197 
198 // -----------------------------------------------------------------------------
199 bool AddTableDialogContext::allowViews() const
200 {
201     return m_rController.allowViews();
202 }
203 
204 // -----------------------------------------------------------------------------
205 bool AddTableDialogContext::allowQueries() const
206 {
207     return m_rController.allowQueries();
208 }
209 
210 // -----------------------------------------------------------------------------
211 bool AddTableDialogContext::allowAddition() const
212 {
213     return const_cast< OJoinController& >( m_rController ).getJoinView()->getTableView()->IsAddAllowed();
214 }
215 
216 // -----------------------------------------------------------------------------
217 void AddTableDialogContext::addTableWindow( const String& _rQualifiedTableName, const String& _rAliasName )
218 {
219     getTableView()->AddTabWin( _rQualifiedTableName, _rAliasName, sal_True );
220 }
221 
222 // -----------------------------------------------------------------------------
223 void AddTableDialogContext::onWindowClosing( const Window* _pWindow )
224 {
225     if ( !m_rController.getView() )
226         return;
227 
228     ::dbaui::notifySystemWindow(
229         m_rController.getView(), const_cast< Window* >( _pWindow ), ::comphelper::mem_fun( &TaskPaneList::RemoveWindow ) );
230 
231 	m_rController.InvalidateFeature( ID_BROWSER_ADDTABLE );
232 	m_rController.getView()->GrabFocus();
233 }
234 
235 // -----------------------------------------------------------------------------
236 OJoinTableView* AddTableDialogContext::getTableView() const
237 {
238     if ( m_rController.getJoinView() )
239         return m_rController.getJoinView()->getTableView();
240     return NULL;
241 }
242 
243 // =============================================================================
244 // = OJoinController
245 // =============================================================================
246 
247 DBG_NAME(OJoinController)
248 // -----------------------------------------------------------------------------
249 OJoinController::OJoinController(const Reference< XMultiServiceFactory >& _rM)
250     :OJoinController_BASE(_rM)
251     ,m_pAddTableDialog(NULL)
252 {
253 	DBG_CTOR(OJoinController,NULL);
254 }
255 // -----------------------------------------------------------------------------
256 OJoinController::~OJoinController()
257 {
258 	DBG_DTOR(OJoinController,NULL);
259 }
260 
261 // -----------------------------------------------------------------------------
262 void SAL_CALL OJoinController::disposing( const EventObject& _rSource ) throw(RuntimeException)
263 {
264 	OJoinController_BASE::disposing( _rSource );
265 }
266 
267 // -----------------------------------------------------------------------------
268 OJoinDesignView* OJoinController::getJoinView()
269 {
270 	return static_cast< OJoinDesignView* >( getView() );
271 }
272 
273 // -----------------------------------------------------------------------------
274 void OJoinController::disposing()
275 {
276     {
277 	    ::std::auto_ptr< Window > pEnsureDelete( m_pAddTableDialog );
278 	    m_pAddTableDialog   = NULL;
279     }
280 
281     OJoinController_BASE::disposing();
282 
283     clearView();
284 
285 	m_vTableConnectionData.clear();
286 	m_vTableData.clear();
287 }
288 // -----------------------------------------------------------------------------
289 void OJoinController::reconnect( sal_Bool _bUI )
290 {
291     OJoinController_BASE::reconnect( _bUI );
292     if ( isConnected() && m_pAddTableDialog )
293         m_pAddTableDialog->Update();
294 }
295 
296 // -----------------------------------------------------------------------------
297 void OJoinController::impl_onModifyChanged()
298 {
299     OJoinController_BASE::impl_onModifyChanged();
300     InvalidateFeature( SID_RELATION_ADD_RELATION );
301 }
302 // -----------------------------------------------------------------------------
303 void OJoinController::SaveTabWinPosSize(OTableWindow* pTabWin, long nOffsetX, long nOffsetY)
304 {
305 	// die Daten zum Fenster
306 	TTableWindowData::value_type pData = pTabWin->GetData();
307 	OSL_ENSURE(pData != NULL, "SaveTabWinPosSize : TabWin hat keine Daten !");
308 
309 	// Position & Size der Daten neu setzen (aus den aktuellen Fenster-Parametern)
310 	Point aPos = pTabWin->GetPosPixel();
311 	aPos.X() += nOffsetX;
312 	aPos.Y() += nOffsetY;
313 	pData->SetPosition(aPos);
314 	pData->SetSize(pTabWin->GetSizePixel());
315 
316 }
317 // -----------------------------------------------------------------------------
318 FeatureState OJoinController::GetState(sal_uInt16 _nId) const
319 {
320 	FeatureState aReturn;
321 		// (disabled automatically)
322 	aReturn.bEnabled = sal_True;
323 
324 	switch (_nId)
325 	{
326 		case ID_BROWSER_EDITDOC:
327 			aReturn.bChecked = isEditable();
328 			break;
329 		case ID_BROWSER_ADDTABLE:
330             aReturn.bEnabled = ( getView() != NULL )
331                             && const_cast< OJoinController* >( this )->getJoinView()->getTableView()->IsAddAllowed();
332             aReturn.bChecked = aReturn.bEnabled && m_pAddTableDialog != NULL && m_pAddTableDialog->IsVisible() ;
333             if ( aReturn.bEnabled )
334                 aReturn.sTitle = OAddTableDlg::getDialogTitleForContext( impl_getDialogContext() );
335 			break;
336 
337         default:
338 			aReturn = OJoinController_BASE::GetState(_nId);
339 	}
340 	return aReturn;
341 }
342 
343 // -----------------------------------------------------------------------------
344 AddTableDialogContext& OJoinController::impl_getDialogContext() const
345 {
346     if ( !m_pDialogContext.get() )
347     {
348         OJoinController* pNonConstThis = const_cast< OJoinController* >( this );
349         pNonConstThis->m_pDialogContext.reset( new AddTableDialogContext( *pNonConstThis ) );
350     }
351     return *m_pDialogContext;
352 }
353 
354 // -----------------------------------------------------------------------------
355 void OJoinController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
356 {
357 	switch(_nId)
358 	{
359 		case ID_BROWSER_EDITDOC:
360 			if(isEditable())
361 			{ // the state should be changed to not editable
362 				switch (saveModified())
363 				{
364 					case RET_CANCEL:
365 						// don't change anything here so return
366 						return;
367 					case RET_NO:
368 						reset();
369 						setModified(sal_False);		// and we are not modified yet
370 						break;
371 					default:
372 						break;
373 				}
374 			}
375 			setEditable(!isEditable());
376 			getJoinView()->setReadOnly(!isEditable());
377 			InvalidateAll();
378 			return;
379 		case ID_BROWSER_ADDTABLE:
380 			if ( !m_pAddTableDialog )
381 				m_pAddTableDialog = new OAddTableDlg( getView(), impl_getDialogContext() );
382 
383             if ( m_pAddTableDialog->IsVisible() )
384 			{
385 				m_pAddTableDialog->Show( sal_False );
386 				getView()->GrabFocus();
387 			}
388 			else
389 			{
390 				{
391 					WaitObject aWaitCursor( getView() );
392 					m_pAddTableDialog->Update();
393 				}
394 				m_pAddTableDialog->Show( sal_True );
395 				::dbaui::notifySystemWindow(getView(),m_pAddTableDialog,::comphelper::mem_fun(&TaskPaneList::AddWindow));
396 			}
397 			break;
398 		default:
399 			OJoinController_BASE::Execute(_nId,aArgs);
400 	}
401 	InvalidateFeature(_nId);
402 }
403 // -----------------------------------------------------------------------------
404 void OJoinController::SaveTabWinsPosSize( OJoinTableView::OTableWindowMap* pTabWinList, long nOffsetX, long nOffsetY )
405 {
406 	// Das Loeschen und Neuanlegen der alten Implementation ist unter dem aktuellen Modell nicht mehr richtig : Die TabWins
407 	// habe einen Zeiger auf ihre Daten, verwaltet werden sie aber von mir. Wenn ich die alten loesche, haben die TabWins
408 	// ploetzlich Zeiger auf nicht mehr existente Objekte.
409 	// Wenn die TabWins ein SetData haetten, koennte ich mir das sparen ... haben sie aber nicht, ausserdem muesste ich dann immer
410 	// noch Informationen, die sich eigentlich nicht geaendert haben, auch neu setzen.
411 	// Also loesche ich die TabWinDatas nicht, sondern aktualisiere sie nur.
412 	DBG_ASSERT(m_vTableData.size() == pTabWinList->size(),
413 		"OJoinController::SaveTabWinsPosSize : inkonsistenter Zustand : sollte genausviel TabWinDatas haben wie TabWins !");
414 
415 	OJoinTableView::OTableWindowMap::iterator aIter = pTabWinList->begin();
416     OJoinTableView::OTableWindowMap::iterator aEnd = pTabWinList->end();
417 	for(;aIter != aEnd;++aIter)
418 		SaveTabWinPosSize(aIter->second, nOffsetX, nOffsetY);
419 }
420 // -----------------------------------------------------------------------------
421 void OJoinController::removeConnectionData(const TTableConnectionData::value_type& _pData)
422 {
423 	m_vTableConnectionData.erase( ::std::remove(m_vTableConnectionData.begin(),m_vTableConnectionData.end(),_pData),m_vTableConnectionData.end());
424 }
425 // -----------------------------------------------------------------------------
426 void OJoinController::describeSupportedFeatures()
427 {
428 	OJoinController_BASE::describeSupportedFeatures();
429     implDescribeSupportedFeature( ".uno:Redo",      ID_BROWSER_REDO,    CommandGroup::EDIT );
430 	implDescribeSupportedFeature( ".uno:Save",      ID_BROWSER_SAVEDOC, CommandGroup::DOCUMENT );
431 	implDescribeSupportedFeature( ".uno:Undo",      ID_BROWSER_UNDO,    CommandGroup::EDIT );
432 	implDescribeSupportedFeature( ".uno:AddTable",  ID_BROWSER_ADDTABLE,CommandGroup::EDIT );
433 	implDescribeSupportedFeature( ".uno:EditDoc",   ID_BROWSER_EDITDOC, CommandGroup::EDIT );
434 }
435 // -----------------------------------------------------------------------------
436 sal_Bool SAL_CALL OJoinController::suspend(sal_Bool _bSuspend) throw( RuntimeException )
437 {
438 	if ( getBroadcastHelper().bInDispose || getBroadcastHelper().bDisposed )
439 		return sal_True;
440 
441     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
442 	::osl::MutexGuard aGuard( getMutex() );
443     if ( getView() && getView()->IsInModalMode() )
444         return sal_False;
445 	sal_Bool bCheck = sal_True;
446 	if ( _bSuspend )
447 	{
448 		bCheck = saveModified() != RET_CANCEL;
449 		if ( bCheck )
450 			OSingleDocumentController::suspend(_bSuspend);
451 	}
452 	return bCheck;
453 }
454 // -----------------------------------------------------------------------------
455 void OJoinController::loadTableWindows( const ::comphelper::NamedValueCollection& i_rViewSettings )
456 {
457     m_vTableData.clear();
458 
459     m_aMinimumTableViewSize = Point();
460 
461     Sequence< PropertyValue > aWindowData;
462     aWindowData = i_rViewSettings.getOrDefault( "Tables", aWindowData );
463 
464     const PropertyValue* pTablesIter = aWindowData.getConstArray();
465     const PropertyValue* pTablesEnd = pTablesIter + aWindowData.getLength();
466     for ( ; pTablesIter != pTablesEnd; ++pTablesIter )
467     {
468         ::comphelper::NamedValueCollection aSingleTableData( pTablesIter->Value );
469         loadTableWindow( aSingleTableData );
470     }
471     if ( m_aMinimumTableViewSize != Point() )
472     {
473         getJoinView()->getScrollHelper()->resetRange( m_aMinimumTableViewSize );
474     }
475 }
476 
477 // -----------------------------------------------------------------------------
478 void OJoinController::loadTableWindow( const ::comphelper::NamedValueCollection& i_rTableWindowSettings )
479 {
480 	sal_Int32 nX = -1, nY = -1, nHeight = -1, nWidth = -1;
481 
482     ::rtl::OUString sComposedName,sTableName,sWindowName;
483     sal_Bool bShowAll = false;
484 
485     sComposedName = i_rTableWindowSettings.getOrDefault( "ComposedName", sComposedName );
486     sTableName = i_rTableWindowSettings.getOrDefault( "TableName", sTableName );
487     sWindowName = i_rTableWindowSettings.getOrDefault( "WindowName", sWindowName );
488     nY = i_rTableWindowSettings.getOrDefault( "WindowTop", nY );
489     nX = i_rTableWindowSettings.getOrDefault( "WindowLeft", nX );
490     nWidth = i_rTableWindowSettings.getOrDefault( "WindowWidth", nWidth );
491     nHeight = i_rTableWindowSettings.getOrDefault( "WindowHeight", nHeight );
492     bShowAll = i_rTableWindowSettings.getOrDefault( "ShowAll", bShowAll );
493 
494     TTableWindowData::value_type pData = createTableWindowData(sComposedName,sTableName,sWindowName);
495     if ( pData )
496     {
497 	    pData->SetPosition(Point(nX,nY));
498 	    pData->SetSize( Size( nWidth, nHeight ) );
499         pData->ShowAll(bShowAll);
500 	    m_vTableData.push_back(pData);
501         if ( m_aMinimumTableViewSize.X() < (nX+nWidth) )
502             m_aMinimumTableViewSize.X() = (nX+nWidth);
503         if ( m_aMinimumTableViewSize.Y() < (nY+nHeight) )
504             m_aMinimumTableViewSize.Y() = (nY+nHeight);
505     }
506 }
507 // -----------------------------------------------------------------------------
508 void OJoinController::saveTableWindows( ::comphelper::NamedValueCollection& o_rViewSettings ) const
509 {
510 	if ( !m_vTableData.empty() )
511 	{
512         ::comphelper::NamedValueCollection aAllTablesData;
513 
514         TTableWindowData::const_iterator aIter = m_vTableData.begin();
515 		TTableWindowData::const_iterator aEnd = m_vTableData.end();
516 		for ( sal_Int32 i = 1; aIter != aEnd; ++aIter, ++i )
517 		{
518             ::comphelper::NamedValueCollection aWindowData;
519 			aWindowData.put( "ComposedName", (*aIter)->GetComposedName() );
520 			aWindowData.put( "TableName", (*aIter)->GetTableName() );
521 			aWindowData.put( "WindowName", (*aIter)->GetWinName() );
522 			aWindowData.put( "WindowTop", static_cast<sal_Int32>((*aIter)->GetPosition().Y()) );
523 			aWindowData.put( "WindowLeft", static_cast<sal_Int32>((*aIter)->GetPosition().X()) );
524 			aWindowData.put( "WindowWidth", static_cast<sal_Int32>((*aIter)->GetSize().Width()) );
525 			aWindowData.put( "WindowHeight", static_cast<sal_Int32>((*aIter)->GetSize().Height()) );
526 			aWindowData.put( "ShowAll", (*aIter)->IsShowAll() );
527 
528             const ::rtl::OUString sTableName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Table" ) ) + ::rtl::OUString::valueOf( i ) );
529             aAllTablesData.put( sTableName, aWindowData.getPropertyValues() );
530 		}
531 
532         o_rViewSettings.put( "Tables", aAllTablesData.getPropertyValues() );
533 	}
534 }
535 // -----------------------------------------------------------------------------
536 TTableWindowData::value_type OJoinController::createTableWindowData(const ::rtl::OUString& _sComposedName,const ::rtl::OUString& _sTableName,const ::rtl::OUString& _sWindowName)
537 {
538     OJoinDesignView* pView = getJoinView();
539 	if( pView )
540 		return pView->getTableView()->createTableWindowData(_sComposedName,_sTableName,_sWindowName);
541     OSL_ENSURE(0,"We should never ever reach this point!");
542 
543     return TTableWindowData::value_type();
544 }
545 // .............................................................................
546 }   // namespace dbaui
547 // .............................................................................
548