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