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