xref: /trunk/main/dbaccess/source/ui/dlg/adtabdlg.cxx (revision cdf0e10c)
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 "adtabdlg.hxx"
32 #include "adtabdlg.hrc"
33 #include "sqlmessage.hxx"
34 #include <tools/debug.hxx>
35 #include <tools/diagnose_ex.h>
36 #include <svtools/localresaccess.hxx>
37 #include "dbaccess_helpid.hrc"
38 #include "dbu_resource.hrc"
39 #include "dbu_dlg.hrc"
40 #include <sfx2/sfxsids.hrc>
41 #include "QueryTableView.hxx"
42 #include "QueryDesignView.hxx"
43 #include "querycontroller.hxx"
44 #include <connectivity/dbtools.hxx>
45 #include "browserids.hxx"
46 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
47 #include <com/sun/star/sdbcx/XViewsSupplier.hpp>
48 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
49 #include <com/sun/star/container/XNameAccess.hpp>
50 #include "UITools.hxx"
51 #include "imageprovider.hxx"
52 
53 #include <comphelper/containermultiplexer.hxx>
54 #include "cppuhelper/basemutex.hxx"
55 #include <algorithm>
56 
57 // slot ids
58 using namespace dbaui;
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::uno;
61 using namespace ::com::sun::star::container;
62 using namespace ::com::sun::star::sdb;
63 using namespace ::com::sun::star::sdbc;
64 using namespace ::com::sun::star::sdbcx;
65 using namespace dbtools;
66 
67 //==============================================================================
68 //= TableObjectListFacade
69 //==============================================================================
70 TableObjectListFacade::~TableObjectListFacade()
71 {
72 }
73 
74 //==============================================================================
75 //= TableListFacade
76 //==============================================================================
77 class TableListFacade : public ::cppu::BaseMutex
78                     ,   public TableObjectListFacade
79                     ,   public ::comphelper::OContainerListener
80 {
81     OTableTreeListBox&          m_rTableList;
82     Reference< XConnection >    m_xConnection;
83     ::rtl::Reference< comphelper::OContainerListenerAdapter>
84                                 m_pContainerListener;
85     bool                        m_bAllowViews;
86 
87 public:
88     TableListFacade( OTableTreeListBox& _rTableList, const Reference< XConnection >& _rxConnection )
89         : ::comphelper::OContainerListener(m_aMutex)
90         ,m_rTableList( _rTableList )
91         ,m_xConnection( _rxConnection )
92         ,m_bAllowViews(true)
93     {
94     }
95     virtual ~TableListFacade();
96 
97 
98 private:
99     virtual void    updateTableObjectList( bool _bAllowViews );
100     virtual String  getSelectedName( String& _out_rAliasName ) const;
101     virtual bool    isLeafSelected() const;
102     // OContainerListener
103     virtual void _elementInserted( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException);
104 	virtual void _elementRemoved( const  ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException);
105 	virtual void _elementReplaced( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException);
106 };
107 
108 TableListFacade::~TableListFacade()
109 {
110     if ( m_pContainerListener.is() )
111         m_pContainerListener->dispose();
112 }
113 //------------------------------------------------------------------------------
114 String TableListFacade::getSelectedName( String& _out_rAliasName ) const
115 {
116 	SvLBoxEntry* pEntry = m_rTableList.FirstSelected();
117     if ( !pEntry )
118         return String();
119 
120     ::rtl::OUString aCatalog, aSchema, aTableName;
121 	SvLBoxEntry* pSchema = m_rTableList.GetParent(pEntry);
122 	if(pSchema && pSchema != m_rTableList.getAllObjectsEntry())
123 	{
124 		SvLBoxEntry* pCatalog = m_rTableList.GetParent(pSchema);
125 		if(pCatalog && pCatalog != m_rTableList.getAllObjectsEntry())
126 			aCatalog = m_rTableList.GetEntryText(pCatalog);
127 		aSchema = m_rTableList.GetEntryText(pSchema);
128 	}
129 	aTableName = m_rTableList.GetEntryText(pEntry);
130 
131 	::rtl::OUString aComposedName;
132 	try
133 	{
134         Reference< XDatabaseMetaData > xMeta( m_xConnection->getMetaData(), UNO_QUERY_THROW );
135         if (  !aCatalog.getLength()
136 			&& aSchema.getLength()
137 			&& xMeta->supportsCatalogsInDataManipulation()
138 			&& !xMeta->supportsSchemasInDataManipulation() )
139 		{
140 			aCatalog = aSchema;
141 			aSchema = ::rtl::OUString();
142 		}
143 
144 		aComposedName = ::dbtools::composeTableName(
145             xMeta, aCatalog, aSchema, aTableName, sal_False, ::dbtools::eInDataManipulation );
146 	}
147 	catch ( const Exception& )
148 	{
149         DBG_UNHANDLED_EXCEPTION();
150 	}
151 
152     _out_rAliasName = aTableName;
153     return aComposedName;
154 }
155 // -----------------------------------------------------------------------------
156 void TableListFacade::_elementInserted( const container::ContainerEvent& /*_rEvent*/ )  throw(::com::sun::star::uno::RuntimeException)
157 {
158     updateTableObjectList(m_bAllowViews);
159 }
160 // -----------------------------------------------------------------------------
161 void TableListFacade::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException)
162 {
163     updateTableObjectList(m_bAllowViews);
164 }
165 // -----------------------------------------------------------------------------
166 void TableListFacade::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException)
167 {
168 }
169 //------------------------------------------------------------------------------
170 void TableListFacade::updateTableObjectList( bool _bAllowViews )
171 {
172     m_bAllowViews = _bAllowViews;
173     m_rTableList.Clear();
174     try
175     {
176 	    Reference< XTablesSupplier > xTableSupp( m_xConnection, UNO_QUERY_THROW );
177 
178 	    Reference< XViewsSupplier > xViewSupp;
179 	    Reference< XNameAccess > xTables, xViews;
180 	    Sequence< ::rtl::OUString > sTables, sViews;
181 
182 	    xTables = xTableSupp->getTables();
183 	    if ( xTables.is() )
184         {
185             if ( !m_pContainerListener.is() )
186             {
187                 Reference< XContainer> xContainer(xTables,uno::UNO_QUERY);
188                 if ( xContainer.is() )
189                     m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
190             }
191 		    sTables = xTables->getElementNames();
192         } // if ( xTables.is() )
193 
194 	    xViewSupp.set( xTableSupp, UNO_QUERY );
195 	    if ( xViewSupp.is() )
196 	    {
197 		    xViews = xViewSupp->getViews();
198 		    if ( xViews.is() )
199 			    sViews = xViews->getElementNames();
200 	    }
201 
202         // if no views are allowed remove the views also out the table name filter
203 	    if ( !_bAllowViews )
204 	    {
205 		    const ::rtl::OUString* pTableBegin	= sTables.getConstArray();
206 		    const ::rtl::OUString* pTableEnd	= pTableBegin + sTables.getLength();
207 		    ::std::vector< ::rtl::OUString > aTables(pTableBegin,pTableEnd);
208 
209 		    const ::rtl::OUString* pViewBegin = sViews.getConstArray();
210 		    const ::rtl::OUString* pViewEnd	  = pViewBegin + sViews.getLength();
211 		    ::comphelper::TStringMixEqualFunctor aEqualFunctor;
212 		    for(;pViewBegin != pViewEnd;++pViewBegin)
213 			    aTables.erase(::std::remove_if(aTables.begin(),aTables.end(),::std::bind2nd(aEqualFunctor,*pViewBegin)),aTables.end());
214 		    ::rtl::OUString* pTables = aTables.empty() ? 0 : &aTables[0];
215 		    sTables = Sequence< ::rtl::OUString>(pTables, aTables.size());
216 		    sViews = Sequence< ::rtl::OUString>();
217 	    }
218 
219 	    m_rTableList.UpdateTableList( m_xConnection, sTables, sViews );
220 	    SvLBoxEntry* pEntry = m_rTableList.First();
221 	    while( pEntry && m_rTableList.GetModel()->HasChilds( pEntry ) )
222 	    {
223 		    m_rTableList.Expand( pEntry );
224 		    pEntry = m_rTableList.Next( pEntry );
225 	    }
226 	    if ( pEntry )
227 		    m_rTableList.Select(pEntry);
228     }
229     catch( const Exception& )
230     {
231     	DBG_UNHANDLED_EXCEPTION();
232     }
233 }
234 
235 //------------------------------------------------------------------------------
236 bool TableListFacade::isLeafSelected() const
237 {
238 	SvLBoxEntry* pEntry = m_rTableList.FirstSelected();
239 	return pEntry && !m_rTableList.GetModel()->HasChilds( pEntry );
240 }
241 
242 //==============================================================================
243 //= QueryListFacade
244 //==============================================================================
245 class QueryListFacade : public ::cppu::BaseMutex
246                     ,   public TableObjectListFacade
247                     ,   public ::comphelper::OContainerListener
248 {
249     SvTreeListBox&              m_rQueryList;
250     Reference< XConnection >    m_xConnection;
251     ::rtl::Reference< comphelper::OContainerListenerAdapter>
252                                 m_pContainerListener;
253 
254 public:
255     QueryListFacade( SvTreeListBox& _rQueryList, const Reference< XConnection >& _rxConnection )
256         : ::comphelper::OContainerListener(m_aMutex)
257         ,m_rQueryList( _rQueryList )
258         ,m_xConnection( _rxConnection )
259     {
260     }
261     virtual ~QueryListFacade();
262 private:
263     virtual void    updateTableObjectList( bool _bAllowViews );
264     virtual String  getSelectedName( String& _out_rAliasName ) const;
265     virtual bool    isLeafSelected() const;
266     // OContainerListener
267     virtual void _elementInserted( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException);
268 	virtual void _elementRemoved( const  ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException);
269 	virtual void _elementReplaced( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException);
270 };
271 QueryListFacade::~QueryListFacade()
272 {
273     if ( m_pContainerListener.is() )
274         m_pContainerListener->dispose();
275 }
276 // -----------------------------------------------------------------------------
277 void QueryListFacade::_elementInserted( const container::ContainerEvent& _rEvent )  throw(::com::sun::star::uno::RuntimeException)
278 {
279     ::rtl::OUString sName;
280     if ( _rEvent.Accessor >>= sName )
281         m_rQueryList.InsertEntry( sName );
282 }
283 // -----------------------------------------------------------------------------
284 void QueryListFacade::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException)
285 {
286     updateTableObjectList(true);
287 }
288 // -----------------------------------------------------------------------------
289 void QueryListFacade::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException)
290 {
291 }
292 
293 //------------------------------------------------------------------------------
294 void QueryListFacade::updateTableObjectList( bool /*_bAllowViews*/ )
295 {
296     m_rQueryList.Clear();
297     try
298     {
299         ImageProvider aImageProvider( m_xConnection );
300         Image aQueryImage( aImageProvider.getDefaultImage( DatabaseObject::QUERY, false ) );
301         Image aQueryImageHC( aImageProvider.getDefaultImage( DatabaseObject::QUERY, true ) );
302 
303         m_rQueryList.SetDefaultExpandedEntryBmp( aQueryImage, BMP_COLOR_NORMAL );
304         m_rQueryList.SetDefaultCollapsedEntryBmp( aQueryImage, BMP_COLOR_NORMAL );
305         m_rQueryList.SetDefaultExpandedEntryBmp( aQueryImageHC, BMP_COLOR_HIGHCONTRAST );
306         m_rQueryList.SetDefaultCollapsedEntryBmp( aQueryImageHC, BMP_COLOR_HIGHCONTRAST );
307 
308         Reference< XQueriesSupplier > xSuppQueries( m_xConnection, UNO_QUERY_THROW );
309         Reference< XNameAccess > xQueries( xSuppQueries->getQueries(), UNO_QUERY_THROW );
310         if ( !m_pContainerListener.is() )
311         {
312             Reference< XContainer> xContainer(xQueries,UNO_QUERY_THROW);
313             m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
314         }
315         Sequence< ::rtl::OUString > aQueryNames = xQueries->getElementNames();
316 
317         const ::rtl::OUString* pQuery = aQueryNames.getConstArray();
318         const ::rtl::OUString* pQueryEnd = aQueryNames.getConstArray() + aQueryNames.getLength();
319         while ( pQuery != pQueryEnd )
320             m_rQueryList.InsertEntry( *pQuery++ );
321     }
322     catch( const Exception& )
323     {
324     	DBG_UNHANDLED_EXCEPTION();
325     }
326 }
327 
328 //------------------------------------------------------------------------------
329 String QueryListFacade::getSelectedName( String& _out_rAliasName ) const
330 {
331     String sSelected;
332 	SvLBoxEntry* pEntry = m_rQueryList.FirstSelected();
333     if ( pEntry )
334         sSelected = _out_rAliasName = m_rQueryList.GetEntryText( pEntry );
335     return sSelected;
336 }
337 
338 //------------------------------------------------------------------------------
339 bool QueryListFacade::isLeafSelected() const
340 {
341 	SvLBoxEntry* pEntry = m_rQueryList.FirstSelected();
342 	return pEntry && !m_rQueryList.GetModel()->HasChilds( pEntry );
343 }
344 
345 //==============================================================================
346 //= OAddTableDlg
347 //==============================================================================
348 //------------------------------------------------------------------------------
349 OAddTableDlg::OAddTableDlg( Window* pParent, IAddTableDialogContext& _rContext )
350 			 :ModelessDialog( pParent, ModuleRes(DLG_JOIN_TABADD) )
351              ,m_aCaseTables( this, ModuleRes( RB_CASE_TABLES ) )
352              ,m_aCaseQueries( this, ModuleRes( RB_CASE_QUERIES ) )
353 			 ,m_aTableList( this, NULL, ModuleRes( LB_TABLE_OR_QUERY ), sal_False )
354 			 ,m_aQueryList( this, ModuleRes( LB_TABLE_OR_QUERY ) )
355 			 ,aAddButton( this, ModuleRes( PB_ADDTABLE ) )
356 			 ,aCloseButton( this, ModuleRes( PB_CLOSE ) )
357 			 ,aHelpButton( this, ModuleRes( PB_HELP ) )
358 			 ,m_rContext( _rContext )
359 {
360 	// der Close-Button hat schon einen Standard-Help-Text, den ich aber hier nicht haben moechte, also den Text ruecksetzen
361 	// und eine neue ID verteilen
362 	aCloseButton.SetHelpText(String());
363 	aCloseButton.SetHelpId(HID_JOINSH_ADDTAB_CLOSE);
364 
365 	m_aTableList.SetHelpId( HID_JOINSH_ADDTAB_TABLELIST );
366     m_aQueryList.SetHelpId( HID_JOINSH_ADDTAB_QUERYLIST );
367 
368 	//////////////////////////////////////////////////////////////////////
369     m_aCaseTables.SetClickHdl( LINK( this, OAddTableDlg, OnTypeSelected ) );
370     m_aCaseQueries.SetClickHdl( LINK( this, OAddTableDlg, OnTypeSelected ) );
371 	aAddButton.SetClickHdl( LINK( this, OAddTableDlg, AddClickHdl ) );
372 	aCloseButton.SetClickHdl( LINK( this, OAddTableDlg, CloseClickHdl ) );
373 	m_aTableList.SetDoubleClickHdl( LINK( this, OAddTableDlg, TableListDoubleClickHdl ) );
374 	m_aTableList.SetSelectHdl( LINK( this, OAddTableDlg, TableListSelectHdl ) );
375 	m_aQueryList.SetDoubleClickHdl( LINK( this, OAddTableDlg, TableListDoubleClickHdl ) );
376 	m_aQueryList.SetSelectHdl( LINK( this, OAddTableDlg, TableListSelectHdl ) );
377 
378 	//////////////////////////////////////////////////////////////////////
379 	m_aTableList.EnableInplaceEditing( sal_False );
380 	m_aTableList.SetStyle(m_aTableList.GetStyle() | WB_BORDER | WB_HASLINES |WB_HASBUTTONS | WB_HASBUTTONSATROOT | WB_HASLINESATROOT | WB_SORT | WB_HSCROLL );
381 	m_aTableList.EnableCheckButton( NULL ); // do not show any buttons
382 	m_aTableList.SetSelectionMode( SINGLE_SELECTION );
383 	m_aTableList.notifyHiContrastChanged();
384     m_aTableList.suppressEmptyFolders();
385 
386 	//////////////////////////////////////////////////////////////////////
387     m_aQueryList.EnableInplaceEditing( sal_False );
388 	m_aQueryList.SetSelectionMode( SINGLE_SELECTION );
389 
390 	//////////////////////////////////////////////////////////////////////
391     if ( !m_rContext.allowQueries() )
392     {
393         m_aCaseTables.Hide();
394         m_aCaseQueries.Hide();
395 
396         long nPixelDiff = m_aTableList.GetPosPixel().Y() - m_aCaseTables.GetPosPixel().Y();
397 
398         Point aListPos( m_aTableList.GetPosPixel() );
399         aListPos.Y() -= nPixelDiff;
400 
401         Size aListSize( m_aTableList.GetSizePixel() );
402         aListSize.Height() += nPixelDiff;
403 
404         m_aTableList.SetPosSizePixel( aListPos, aListSize );
405     }
406 
407     FreeResource();
408 
409     SetText( getDialogTitleForContext( m_rContext ) );
410 }
411 
412 //------------------------------------------------------------------------------
413 OAddTableDlg::~OAddTableDlg()
414 {
415     m_rContext.onWindowClosing( this );
416 }
417 
418 //------------------------------------------------------------------------------
419 void OAddTableDlg::impl_switchTo( ObjectList _eList )
420 {
421     switch ( _eList )
422     {
423     case Tables:
424         m_aTableList.Show( sal_True );  m_aCaseTables.Check( sal_True );
425         m_aQueryList.Show( sal_False ); m_aCaseQueries.Check( sal_False );
426         m_pCurrentList.reset( new TableListFacade( m_aTableList, m_rContext.getConnection() ) );
427         m_aTableList.GrabFocus();
428         break;
429 
430     case Queries:
431         m_aTableList.Show( sal_False ); m_aCaseTables.Check( sal_False );
432         m_aQueryList.Show( sal_True );  m_aCaseQueries.Check( sal_True );
433         m_pCurrentList.reset( new QueryListFacade( m_aQueryList, m_rContext.getConnection() ) );
434         m_aQueryList.GrabFocus();
435         break;
436     }
437     m_pCurrentList->updateTableObjectList( m_rContext.allowViews() );
438 }
439 
440 //------------------------------------------------------------------------------
441 void OAddTableDlg::Update()
442 {
443     if ( !m_pCurrentList.get() )
444         impl_switchTo( Tables );
445     else
446         m_pCurrentList->updateTableObjectList( m_rContext.allowViews() );
447 }
448 
449 //------------------------------------------------------------------------------
450 void OAddTableDlg::impl_addTable()
451 {
452     if ( m_pCurrentList->isLeafSelected() )
453     {
454         String sSelectedName, sAliasName;
455         sSelectedName = m_pCurrentList->getSelectedName( sAliasName );
456 
457         m_rContext.addTableWindow( sSelectedName, sAliasName );
458     }
459 }
460 
461 //------------------------------------------------------------------------------
462 IMPL_LINK( OAddTableDlg, AddClickHdl, Button*, /*pButton*/ )
463 {
464 	TableListDoubleClickHdl(NULL);
465 	return 0;
466 }
467 
468 //------------------------------------------------------------------------------
469 IMPL_LINK( OAddTableDlg, TableListDoubleClickHdl, void*, /*EMPTY_ARG*/ )
470 {
471 	if ( impl_isAddAllowed() )
472     {
473 		impl_addTable();
474 	    if ( !impl_isAddAllowed() )
475 		    Close();
476         return 1L;  // handled
477     }
478 
479 	return 0L;  // not handled
480 }
481 
482 //------------------------------------------------------------------------------
483 IMPL_LINK( OAddTableDlg, TableListSelectHdl, void*, /*EMPTY_ARG*/ )
484 {
485 	aAddButton.Enable( m_pCurrentList->isLeafSelected() );
486 	return 0;
487 }
488 
489 //------------------------------------------------------------------------------
490 IMPL_LINK( OAddTableDlg, CloseClickHdl, Button*, /*pButton*/ )
491 {
492 	return Close();
493 }
494 
495 //------------------------------------------------------------------------------
496 IMPL_LINK( OAddTableDlg, OnTypeSelected, void*, /*EMPTY_ARG*/ )
497 {
498     if ( m_aCaseTables.IsChecked() )
499         impl_switchTo( Tables );
500     else
501         impl_switchTo( Queries );
502     return 0;
503 }
504 
505 //------------------------------------------------------------------------------
506 sal_Bool OAddTableDlg::Close()
507 {
508     m_rContext.onWindowClosing( this );
509 	return ModelessDialog::Close();
510 }
511 
512 //------------------------------------------------------------------------------
513 bool OAddTableDlg::impl_isAddAllowed()
514 {
515 	return	m_rContext.allowAddition();
516 }
517 
518 //------------------------------------------------------------------------------
519 String OAddTableDlg::getDialogTitleForContext( IAddTableDialogContext& _rContext )
520 {
521     String sTitle;
522 
523     ::svt::OLocalResourceAccess aLocalRes( ModuleRes( DLG_JOIN_TABADD ), RSC_MODELESSDIALOG );
524     if ( _rContext.allowQueries() )
525         sTitle = String( ModuleRes( STR_ADD_TABLE_OR_QUERY ) );
526     else
527         sTitle = String( ModuleRes( STR_ADD_TABLES ) );
528 
529     return sTitle;
530 }
531 
532 // -----------------------------------------------------------------------------
533 
534