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