xref: /trunk/main/dbaccess/source/ui/querydesign/QueryTableView.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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 #ifndef DBAUI_QUERYTABLEVIEW_HXX
32 #include "QueryTableView.hxx"
33 #endif
34 #ifndef DBAUI_TABLEFIELDINFO_HXX
35 #include "TableFieldInfo.hxx"
36 #endif
37 #ifndef DBAUI_TABLEFIELDDESC_HXX
38 #include "TableFieldDescription.hxx"
39 #endif
40 #ifndef _TOOLS_DEBUG_HXX
41 #include <tools/debug.hxx>
42 #endif
43 #ifndef TOOLS_DIAGNOSE_EX_H
44 #include <tools/diagnose_ex.h>
45 #endif
46 #ifndef _DBA_DBACCESS_HELPID_HRC_
47 #include "dbaccess_helpid.hrc"
48 #endif
49 #ifndef DBAUI_QUERY_TABLEWINDOW_HXX
50 #include "QTableWindow.hxx"
51 #endif
52 #ifndef DBAUI_QUERYTABLECONNECTION_HXX
53 #include "QTableConnection.hxx"
54 #endif
55 #ifndef DBAUI_QTABLECONNECTIONDATA_HXX
56 #include "QTableConnectionData.hxx"
57 #endif
58 #ifndef DBAUI_QUERYDESIGNVIEW_HXX
59 #include "QueryDesignView.hxx"
60 #endif
61 #ifndef DBAUI_QUERYCONTROLLER_HXX
62 #include "querycontroller.hxx"
63 #endif
64 #ifndef DBAUI_QUERYADDTABCONNUNDOACTION_HXX
65 #include "QueryAddTabConnUndoAction.hxx"
66 #endif
67 #ifndef DBAUI_QUERYTABWINSHOWUNDOACT_HXX
68 #include "QueryTabWinShowUndoAct.hxx"
69 #endif
70 #ifndef DBACCESS_UI_BROWSER_ID_HXX
71 #include "browserids.hxx"
72 #endif
73 #ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_
74 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
75 #endif
76 #ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_
77 #include <com/sun/star/sdbc/XConnection.hpp>
78 #endif
79 #ifndef _COM_SUN_STAR_SDBCX_XKEYSSUPPLIER_HPP_
80 #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
81 #endif
82 #ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_
83 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
84 #endif
85 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
86 #ifndef DBACCESS_JACCESS_HXX
87 #include "JAccess.hxx"
88 #endif
89 #ifndef _COM_SUN_STAR_SDBCX_KEYTYPE_HPP_
90 #include <com/sun/star/sdbcx/KeyType.hpp>
91 #endif
92 #ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_
93 #include <com/sun/star/container/XIndexAccess.hpp>
94 #endif
95 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
96 #include <com/sun/star/beans/XPropertySet.hpp>
97 #endif
98 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
99 #include "dbustrings.hrc"
100 #endif
101 #ifndef _CONNECTIVITY_DBTOOLS_HXX_
102 #include <connectivity/dbtools.hxx>
103 #endif
104 #ifndef _COMPHELPER_SEQUENCE_HXX_
105 #include <comphelper/sequence.hxx>
106 #endif
107 #ifndef DBAUI_QUERYDLG_HXX
108 #include "querydlg.hxx"
109 #endif
110 #ifndef DBAUI_JOINEXCHANGE_HXX
111 #include "JoinExchange.hxx"
112 #endif
113 #ifndef _COMPHELPER_EXTRACT_HXX_
114 #include <comphelper/extract.hxx>
115 #endif
116 #ifndef DBAUI_QUERYDESIGNVIEW_HXX
117 #include "QueryDesignView.hxx"
118 #endif
119 #ifndef _DBU_QRY_HRC_
120 #include "dbu_qry.hrc"
121 #endif
122 #ifndef _SV_MSGBOX_HXX
123 #include <vcl/msgbox.hxx>
124 #endif
125 
126 using namespace dbaui;
127 using namespace ::com::sun::star::uno;
128 using namespace ::com::sun::star::sdbc;
129 using namespace ::com::sun::star::sdbcx;
130 using namespace ::com::sun::star::beans;
131 using namespace ::com::sun::star::container;
132 using namespace ::com::sun::star::accessibility;
133 
134 //------------------------------------------------------------------------------
135 namespace
136 {
137     // -----------------------------------------------------------------------------
138     sal_Bool isColumnInKeyType(const Reference<XIndexAccess>& _rxKeys,const ::rtl::OUString& _rColumnName,sal_Int32 _nKeyType)
139     {
140         sal_Bool bReturn = sal_False;
141         if(_rxKeys.is())
142         {
143             Reference<XColumnsSupplier> xColumnsSupplier;
144             // search the one and only primary key
145             const sal_Int32 nCount = _rxKeys->getCount();
146             for(sal_Int32 i=0;i< nCount;++i)
147             {
148                 Reference<XPropertySet> xProp(_rxKeys->getByIndex(i),UNO_QUERY);
149                 if(xProp.is())
150                 {
151                     sal_Int32 nKeyType = 0;
152                     xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType;
153                     if(_nKeyType == nKeyType)
154                     {
155                         xColumnsSupplier.set(xProp,UNO_QUERY);
156                         if(xColumnsSupplier.is())
157                         {
158                             Reference<XNameAccess> xColumns = xColumnsSupplier->getColumns();
159                             if(xColumns.is() && xColumns->hasByName(_rColumnName))
160                             {
161                                 bReturn = sal_True;
162                                 break;
163                             }
164                         }
165                     }
166                 }
167             }
168         }
169         return bReturn;
170     }
171     // -----------------------------------------------------------------------------
172     /** appends a new TabAdd Undo action at controller
173         @param  _pView          the view which we use
174         @param  _pUndoAction    the undo action which should be added
175         @param  _pConnection    the connection for which the undo action should be appended
176         @param  _bOwner         is the undo action the owner
177     */
178     // -----------------------------------------------------------------------------
179     void addUndoAction( OQueryTableView* _pView,
180                         OQueryTabConnUndoAction* _pUndoAction,
181                         OQueryTableConnection* _pConnection,
182                         sal_Bool _bOwner = sal_False)
183     {
184         _pUndoAction->SetOwnership(_bOwner);
185         _pUndoAction->SetConnection(_pConnection);
186         _pView->getDesignView()->getController().addUndoActionAndInvalidate(_pUndoAction);
187     }
188     // -----------------------------------------------------------------------------
189     /** openJoinDialog opens the join dialog with this connection data
190         @param  _pView              the view which we use
191         @param  _pConnectionData    the connection data
192 
193         @return true when OK was pressed otherwise false
194     */
195     sal_Bool openJoinDialog(OQueryTableView* _pView,const TTableConnectionData::value_type& _pConnectionData,sal_Bool _bSelectableTables)
196     {
197         OQueryTableConnectionData* pData = static_cast< OQueryTableConnectionData*>(_pConnectionData.get());
198 
199         DlgQryJoin aDlg(_pView,_pConnectionData,_pView->GetTabWinMap(),_pView->getDesignView()->getController().getConnection(),_bSelectableTables);
200         sal_Bool bOk = aDlg.Execute() == RET_OK;
201         if( bOk )
202         {
203             pData->SetJoinType(aDlg.GetJoinType());
204             _pView->getDesignView()->getController().setModified(sal_True);
205         }
206 
207         return bOk;
208     }
209     // -----------------------------------------------------------------------------
210     /** connectionModified adds an undo action for the modified connection and forces an redraw
211         @param  _pView              the view which we use
212         @param  _pConnection    the connection which was modified
213         @param  _bAddUndo       true when an undo action should be appended
214     */
215     void connectionModified(OQueryTableView* _pView,
216                             OTableConnection* _pConnection,
217                             sal_Bool _bAddUndo)
218     {
219         OSL_ENSURE(_pConnection,"Invalid connection!");
220         _pConnection->UpdateLineList();
221 
222         // add an undo action
223         if ( _bAddUndo )
224             addUndoAction(  _pView,
225                             new OQueryAddTabConnUndoAction(_pView),
226                             static_cast< OQueryTableConnection*>(_pConnection));
227         // redraw
228         _pConnection->RecalcLines();
229         // force an invalidation of the bounding rectangle
230         _pConnection->InvalidateConnection();
231 
232         _pView->Invalidate(INVALIDATE_NOCHILDREN);
233     }
234     // -----------------------------------------------------------------------------
235     void addConnections(OQueryTableView* _pView,
236                         const OQueryTableWindow& _rSource,
237                         const OQueryTableWindow& _rDest,
238                         const Reference<XNameAccess>& _rxSourceForeignKeyColumns)
239     {
240         if ( _rSource.GetData()->isQuery() || _rDest.GetData()->isQuery() )
241             // nothing to do if one of both denotes a query
242             return;
243 
244         // we found a table in our view where we can insert some connections
245         // the key columns have a property called RelatedColumn
246         // OQueryTableConnectionData aufbauen
247         OQueryTableConnectionData* pNewConnData = new OQueryTableConnectionData( _rSource.GetData(), _rDest.GetData() );
248         TTableConnectionData::value_type aNewConnData(pNewConnData);
249 
250         Reference<XIndexAccess> xReferencedKeys( _rDest.GetData()->getKeys());
251         ::rtl::OUString sRelatedColumn;
252 
253         // iterate through all foreignkey columns to create the connections
254         Sequence< ::rtl::OUString> aElements(_rxSourceForeignKeyColumns->getElementNames());
255         const ::rtl::OUString* pIter = aElements.getConstArray();
256         const ::rtl::OUString* pEnd   = pIter + aElements.getLength();
257         for(sal_Int32 i=0;pIter != pEnd;++pIter,++i)
258         {
259             Reference<XPropertySet> xColumn;
260             if ( !( _rxSourceForeignKeyColumns->getByName(*pIter) >>= xColumn ) )
261             {
262                 OSL_ENSURE( false, "addConnections: invalid foreign key column!" );
263                 continue;
264             }
265 
266             pNewConnData->SetFieldType(JTCS_FROM,TAB_NORMAL_FIELD);
267 
268             xColumn->getPropertyValue(PROPERTY_RELATEDCOLUMN) >>= sRelatedColumn;
269             pNewConnData->SetFieldType(JTCS_TO,isColumnInKeyType(xReferencedKeys,sRelatedColumn,KeyType::PRIMARY) ? TAB_PRIMARY_FIELD : TAB_NORMAL_FIELD);
270 
271             {
272                 Sequence< sal_Int16> aFind(::comphelper::findValue(_rSource.GetOriginalColumns()->getElementNames(),*pIter,sal_True));
273                 if(aFind.getLength())
274                     pNewConnData->SetFieldIndex(JTCS_FROM,aFind[0]+1);
275                 else
276                     OSL_ENSURE(0,"Column not found!");
277             }
278             // get the position inside the tabe
279             Reference<XNameAccess> xRefColumns = _rDest.GetOriginalColumns();
280             if(xRefColumns.is())
281             {
282                 Sequence< sal_Int16> aFind(::comphelper::findValue(xRefColumns->getElementNames(),sRelatedColumn,sal_True));
283                 if(aFind.getLength())
284                     pNewConnData->SetFieldIndex(JTCS_TO,aFind[0]+1);
285                 else
286                     OSL_ENSURE(0,"Column not found!");
287             }
288             pNewConnData->AppendConnLine(*pIter,sRelatedColumn);
289 
290             // dann die Conn selber dazu
291             OQueryTableConnection aNewConn(_pView, aNewConnData);
292                 // der Verweis auf die lokale Variable ist unkritisch, da NotifyQueryTabConn eine neue Kopie anlegt
293             // und mir hinzufuegen (wenn nicht schon existent)
294             _pView->NotifyTabConnection(aNewConn, sal_False);
295                 // don't create an Undo-Action for the new connection : the connection is
296                 // covered by the Undo-Action for the tabwin, as the "Undo the insert" will
297                 // automatically remove all connections adjacent to the win.
298                 // (Because of this automatism we would have an ownerhsip ambiguity for
299                 // the connection data if we would insert the conn-Undo-Action)
300                 // FS - 21.10.99 - 69183
301         }
302     }
303 }
304 //==================================================================
305 // class OQueryTableView
306 //==================================================================
307 DBG_NAME(OQueryTableView)
308 //------------------------------------------------------------------------
309 OQueryTableView::OQueryTableView( Window* pParent,OQueryDesignView* pView)
310     : OJoinTableView( pParent,pView)
311 {
312     DBG_CTOR(OQueryTableView,NULL);
313     SetHelpId(HID_CTL_QRYDGNTAB);
314 }
315 
316 //------------------------------------------------------------------------
317 OQueryTableView::~OQueryTableView()
318 {
319     DBG_DTOR(OQueryTableView,NULL);
320 }
321 
322 //------------------------------------------------------------------------
323 sal_Int32 OQueryTableView::CountTableAlias(const String& rName, sal_Int32& rMax)
324 {
325     DBG_CHKTHIS(OQueryTableView,NULL);
326     sal_Int32 nRet = 0;
327 
328     OTableWindowMapIterator aIter = GetTabWinMap()->find(rName);
329     while(aIter != GetTabWinMap()->end())
330     {
331         String aNewName;
332         aNewName = rName;
333         aNewName += '_';
334         aNewName += String::CreateFromInt32(++nRet);
335 
336         aIter = GetTabWinMap()->find(aNewName);
337     }
338 
339     rMax = nRet;
340 
341     return nRet;
342 }
343 //------------------------------------------------------------------------
344 void OQueryTableView::ReSync()
345 {
346     DBG_CHKTHIS(OQueryTableView,NULL);
347     TTableWindowData* pTabWinDataList = m_pView->getController().getTableWindowData();
348     DBG_ASSERT((getTableConnections()->size()==0) && (GetTabWinMap()->size()==0),
349         "vor OQueryTableView::ReSync() bitte ClearAll aufrufen !");
350 
351     // ich brauche eine Sammlung aller Fensternamen, deren Anlegen schief geht, damit ich die entsprechenden Connections
352     // gar nicht erst anlege
353     ::std::vector<String> arrInvalidTables;
354 
355     TTableWindowData::reverse_iterator aIter = pTabWinDataList->rbegin();
356     // Fenster kreieren und einfuegen
357 
358     for(;aIter != pTabWinDataList->rend();++aIter)
359     {
360         OQueryTableWindowData* pData = static_cast<OQueryTableWindowData*>(aIter->get());
361         OTableWindow* pTabWin = createWindow(*aIter);
362 
363         // ich gehe jetzt NICHT ueber ShowTabWin, da dieses die Daten des Fensters in die Liste des Docs einfuegt, was
364         // schlecht waere, denn genau von dort hole ich sie ja gerade
365         // also Schritt fuer Schritt
366         if (!pTabWin->Init())
367         {
368             // das Initialisieren ging schief, dass heisst, dieses TabWin steht nicht zur Verfuegung, also muss ich es inklusive
369             // seiner Daten am Dokument aufraeumen
370             pTabWin->clearListBox();
371             delete pTabWin;
372             arrInvalidTables.push_back(pData->GetAliasName());
373 
374             pTabWinDataList->erase( ::std::remove(pTabWinDataList->begin(),pTabWinDataList->end(),*aIter) ,pTabWinDataList->end());
375             continue;
376         }
377 
378         (*GetTabWinMap())[pData->GetAliasName()] = pTabWin; // am Anfang einfuegen, da ich die DataList ja rueckwaerts durchlaufe
379         // wenn in den Daten keine Position oder Groesse steht -> Default
380         if (!pData->HasPosition() && !pData->HasSize())
381             SetDefaultTabWinPosSize(pTabWin);
382 
383         pTabWin->Show();
384     }
385 
386     // Verbindungen einfuegen
387     TTableConnectionData* pTabConnDataList = m_pView->getController().getTableConnectionData();
388     TTableConnectionData::reverse_iterator aConIter = pTabConnDataList->rbegin();
389 
390     for(;aConIter != pTabConnDataList->rend();++aConIter)
391     {
392         OQueryTableConnectionData* pTabConnData =  static_cast<OQueryTableConnectionData*>(aConIter->get());
393 
394         // gibt es die beiden Tabellen zur Connection ?
395         String strTabExistenceTest = pTabConnData->getReferencingTable()->GetWinName();
396         sal_Bool bInvalid = ::std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end();
397         strTabExistenceTest = pTabConnData->getReferencedTable()->GetWinName();
398         bInvalid = bInvalid && ::std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end();
399 
400         if (bInvalid)
401         {   // nein -> Pech gehabt, die Connection faellt weg
402             pTabConnDataList->erase( ::std::remove(pTabConnDataList->begin(),pTabConnDataList->end(),*aConIter) ,pTabConnDataList->end());
403             continue;
404         }
405 
406         // adds a new connection to join view and notifies our accessible and invaldates the controller
407         addConnection(new OQueryTableConnection(this, *aConIter));
408     }
409 }
410 
411 //------------------------------------------------------------------------
412 void OQueryTableView::ClearAll()
413 {
414     DBG_CHKTHIS(OQueryTableView,NULL);
415     OJoinTableView::ClearAll();
416 
417     SetUpdateMode(sal_True);
418     m_pView->getController().setModified(sal_True);
419 }
420 
421 // -----------------------------------------------------------------------------
422 OTableWindow* OQueryTableView::createWindow(const TTableWindowData::value_type& _pData)
423 {
424     return new OQueryTableWindow(this,_pData);
425 }
426 
427 //------------------------------------------------------------------------------
428 void OQueryTableView::NotifyTabConnection(const OQueryTableConnection& rNewConn, sal_Bool _bCreateUndoAction)
429 {
430     DBG_CHKTHIS(OQueryTableView,NULL);
431     // erst mal schauen, ob ich diese Connection schon habe
432     OQueryTableConnection* pTabConn = NULL;
433     const ::std::vector<OTableConnection*>* pConnections = getTableConnections();
434     ::std::vector<OTableConnection*>::const_iterator aEnd = pConnections->end();
435     ::std::vector<OTableConnection*>::const_iterator aIter = ::std::find(   pConnections->begin(),
436                                                     aEnd,
437                                                     static_cast<const OTableConnection*>(&rNewConn)
438                                                     );
439     if(aIter == aEnd )
440     {
441         aIter = pConnections->begin();
442         for(;aIter != aEnd;++aIter)
443         {
444             if(*static_cast<OQueryTableConnection*>(*aIter) == rNewConn)
445             {
446                 pTabConn = static_cast<OQueryTableConnection*>(*aIter);
447                 break;
448             }
449         }
450     }
451     else
452         pTabConn = static_cast<OQueryTableConnection*>(*aIter);
453     // nein -> einfuegen
454     if (pTabConn == NULL)
455     {
456         // die neuen Daten ...
457         OQueryTableConnectionData* pNewData = static_cast< OQueryTableConnectionData*>(rNewConn.GetData()->NewInstance());
458         pNewData->CopyFrom(*rNewConn.GetData());
459         TTableConnectionData::value_type aData(pNewData);
460         OQueryTableConnection* pNewConn = new OQueryTableConnection(this, aData);
461         GetConnection(pNewConn);
462 
463         connectionModified(this,pNewConn,_bCreateUndoAction);
464     }
465 }
466 // -----------------------------------------------------------------------------
467 OTableWindowData* OQueryTableView::CreateImpl(const ::rtl::OUString& _rComposedName
468                                              ,const ::rtl::OUString& _sTableName
469                                              ,const ::rtl::OUString& _rWinName)
470 {
471     return new OQueryTableWindowData( _rComposedName, _sTableName,_rWinName );
472 }
473 //------------------------------------------------------------------------------
474 void OQueryTableView::AddTabWin(const ::rtl::OUString& _rTableName, const ::rtl::OUString& _rAliasName, sal_Bool bNewTable)
475 {
476     DBG_CHKTHIS(OQueryTableView,NULL);
477     // das ist die aus der Basisklasse geerbte Methode, die fuehre ich auf die an meinem Parent zurueck, die mir eventuell einen
478     // Alias dazu bastelt und das an mein anderes AddTabWin weiterreicht
479 
480     // leider ist _rTableName voll qualifiziert, das OQueryDesignView erwartet aber einen String, der
481     // nur aus Schema und Tabelle besteht und keinen Katalog enthaelt.
482     Reference< XConnection> xConnection = m_pView->getController().getConnection();
483     if(!xConnection.is())
484         return;
485     try
486     {
487         Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
488         ::rtl::OUString sCatalog, sSchema, sTable;
489         ::dbtools::qualifiedNameComponents(xMetaData,
490                                     _rTableName,
491                                     sCatalog,
492                                     sSchema,
493                                     sTable,
494                                     ::dbtools::eInDataManipulation);
495         ::rtl::OUString sRealName(sSchema);
496         if (sRealName.getLength())
497             sRealName+= ::rtl::OUString('.');
498         sRealName += sTable;
499 
500         AddTabWin(_rTableName, sRealName, _rAliasName, bNewTable);
501     }
502     catch(SQLException&)
503     {
504         OSL_ASSERT(!"qualifiedNameComponents");
505     }
506 }
507 // -----------------------------------------------------------------------------
508 // find the table which has a foreign key with this referencedTable name
509 Reference<XPropertySet> getKeyReferencedTo(const Reference<XIndexAccess>& _rxKeys,const ::rtl::OUString& _rReferencedTable)
510 {
511     if(!_rxKeys.is())
512         return Reference<XPropertySet>();
513 
514     if ( !_rxKeys.is() )
515         return Reference<XPropertySet>();
516     // search the one and only primary key
517     const sal_Int32 nCount = _rxKeys->getCount();
518     for(sal_Int32 i=0;i<nCount ;++i)
519     {
520         Reference<XPropertySet> xKey(_rxKeys->getByIndex(i),UNO_QUERY);
521         if(xKey.is())
522         {
523             sal_Int32 nKeyType = 0;
524             xKey->getPropertyValue(PROPERTY_TYPE) >>= nKeyType;
525             if(KeyType::FOREIGN == nKeyType)
526             {
527                 ::rtl::OUString sReferencedTable;
528                 xKey->getPropertyValue(PROPERTY_REFERENCEDTABLE) >>= sReferencedTable;
529                 // TODO check case
530                 if(sReferencedTable == _rReferencedTable)
531                     return xKey;
532             }
533         }
534     }
535     return Reference<XPropertySet>();
536 }
537 //------------------------------------------------------------------------------
538 void OQueryTableView::AddTabWin(const ::rtl::OUString& _rComposedName, const ::rtl::OUString& _rTableName, const ::rtl::OUString& strAlias, sal_Bool bNewTable)
539 {
540     DBG_CHKTHIS(OQueryTableView,NULL);
541     DBG_ASSERT(_rTableName.getLength() || strAlias.getLength(), "OQueryTableView::AddTabWin : kein Tabellen- und kein Aliasname !");
542         // wenn der Tabellenname nicht gesetzt ist, steht das fuer ein Dummy-Fenster, das braucht aber wenigstens einen Alias-Namen
543 
544     // neue Datenstruktur erzeugen
545     // first check if this already hav it's data
546     sal_Bool bAppend = bNewTable;
547     TTableWindowData::value_type pNewTabWinData;
548     TTableWindowData* pWindowData = getDesignView()->getController().getTableWindowData();
549     TTableWindowData::iterator aWinIter = pWindowData->begin();
550     TTableWindowData::iterator aWinEnd = pWindowData->end();
551     for(;aWinIter != aWinEnd;++aWinIter)
552     {
553         pNewTabWinData = *aWinIter;
554         if (pNewTabWinData && pNewTabWinData->GetWinName() == strAlias && pNewTabWinData->GetComposedName() == _rComposedName && pNewTabWinData->GetTableName() == _rTableName)
555             break;
556     }
557     if ( !bAppend )
558         bAppend = ( aWinIter == aWinEnd );
559     if ( bAppend )
560         pNewTabWinData = createTableWindowData(_rComposedName, _rTableName, strAlias);
561         // die TabWinData brauche ich nicht in die entsprechende Liste der DocShell eintragen, das macht ShowTabWin
562 
563     // neues Fenster erzeugen
564     OQueryTableWindow* pNewTabWin = static_cast<OQueryTableWindow*>(createWindow(pNewTabWinData));
565     // das Init kann ich hier weglassen, da das in ShowTabWin passiert
566 
567     // Neue UndoAction
568     OQueryTabWinShowUndoAct* pUndoAction = new OQueryTabWinShowUndoAct(this);
569     pUndoAction->SetTabWin(pNewTabWin); // Fenster
570     sal_Bool bSuccess = ShowTabWin(pNewTabWin, pUndoAction,bAppend);
571     if(!bSuccess)
572     {
573         // reset table window
574         pUndoAction->SetTabWin(NULL);
575         pUndoAction->SetOwnership(sal_False);
576 
577         delete pUndoAction;
578         return;
579     }
580 
581     // Relationen zwischen den einzelnen Tabellen anzeigen
582     OTableWindowMap* pTabWins = GetTabWinMap();
583     if(bNewTable && !pTabWins->empty() && _rTableName.getLength())
584     {
585         modified();
586         if ( m_pAccessible )
587             m_pAccessible->notifyAccessibleEvent(   AccessibleEventId::CHILD,
588                                                     Any(),
589                                                     makeAny(pNewTabWin->GetAccessible())
590                                                     );
591 
592         do {
593 
594         if ( pNewTabWin->GetData()->isQuery() )
595             break;
596 
597         try
598         {
599             //////////////////////////////////////////////////////////////////////
600             // find relations between the table an the tables already inserted
601             Reference< XIndexAccess> xKeyIndex = pNewTabWin->GetData()->getKeys();
602             if ( !xKeyIndex.is() )
603                 break;
604 
605             Reference<XNameAccess> xFKeyColumns;
606             ::rtl::OUString aReferencedTable;
607             Reference<XColumnsSupplier> xColumnsSupplier;
608 
609             const sal_Int32 nKeyCount = xKeyIndex->getCount();
610             for ( sal_Int32 i=0; i<nKeyCount ; ++i )
611             {
612                 Reference< XPropertySet > xProp( xKeyIndex->getByIndex(i), UNO_QUERY_THROW );
613                 xColumnsSupplier.set( xProp, UNO_QUERY_THROW );
614                 xFKeyColumns.set( xColumnsSupplier->getColumns(), UNO_QUERY_THROW );
615 
616                 sal_Int32 nKeyType = 0;
617                 xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType;
618 
619                 switch ( nKeyType )
620                 {
621                 case KeyType::FOREIGN:
622                 {   // our new table has a foreign key
623                     // so look if the referenced table is already in our list
624                     xProp->getPropertyValue(PROPERTY_REFERENCEDTABLE) >>= aReferencedTable;
625                     OSL_ENSURE(aReferencedTable.getLength(),"Foreign key without referencedTableName");
626 
627                     OTableWindowMap::const_iterator aIter = pTabWins->find(aReferencedTable);
628                     OTableWindowMap::const_iterator aEnd  = pTabWins->end();
629                     if(aIter == aEnd)
630                     {
631                         for(aIter = pTabWins->begin();aIter != aEnd;++aIter)
632                         {
633                             OQueryTableWindow* pTabWinTmp = static_cast<OQueryTableWindow*>(aIter->second);
634                             OSL_ENSURE( pTabWinTmp,"TableWindow is null!" );
635                             if ( pTabWinTmp != pNewTabWin && pTabWinTmp->GetComposedName() == aReferencedTable )
636                                 break;
637                         }
638                     }
639                     if ( aIter != aEnd && pNewTabWin != aIter->second )
640                         addConnections( this, *pNewTabWin, *static_cast<OQueryTableWindow*>(aIter->second), xFKeyColumns );
641                 }
642                 break;
643 
644                 case KeyType::PRIMARY:
645                 {
646                     // we have a primary key so look in our list if there exsits a key which this is refered to
647                     OTableWindowMap::const_iterator aIter = pTabWins->begin();
648                     OTableWindowMap::const_iterator aEnd  = pTabWins->end();
649                     for(;aIter != aEnd;++aIter)
650                     {
651                         OQueryTableWindow* pTabWinTmp = static_cast<OQueryTableWindow*>(aIter->second);
652                         if ( pTabWinTmp == pNewTabWin )
653                             continue;
654 
655                         if ( pTabWinTmp->GetData()->isQuery() )
656                             continue;
657 
658                         OSL_ENSURE(pTabWinTmp,"TableWindow is null!");
659                         Reference< XPropertySet > xFKKey = getKeyReferencedTo( pTabWinTmp->GetData()->getKeys(), pNewTabWin->GetComposedName() );
660                         if ( !xFKKey.is() )
661                             continue;
662 
663                         Reference<XColumnsSupplier> xFKColumnsSupplier( xFKKey, UNO_QUERY_THROW );
664                         Reference< XNameAccess > xTColumns( xFKColumnsSupplier->getColumns(), UNO_QUERY_THROW );
665                         addConnections( this, *pTabWinTmp, *pNewTabWin, xTColumns );
666                     }
667                 }
668                 break;
669                 }
670             }
671         }
672         catch( const Exception& )
673         {
674             DBG_UNHANDLED_EXCEPTION();
675         }
676 
677         } while ( false );
678     }
679 
680     // mein Parent brauche ich, da es vom Loeschen erfahren soll
681     m_pView->getController().addUndoActionAndInvalidate( pUndoAction );
682 
683     if (bSuccess && m_lnkTabWinsChangeHandler.IsSet())
684     {
685         TabWinsChangeNotification aHint(TabWinsChangeNotification::AT_ADDED_WIN, pNewTabWin->GetAliasName());
686         m_lnkTabWinsChangeHandler.Call(&aHint);
687     }
688 }
689 // -----------------------------------------------------------------------------
690 // -----------------------------------------------------------------------------
691 void OQueryTableView::AddConnection(const OJoinExchangeData& jxdSource, const OJoinExchangeData& jxdDest)
692 {
693     DBG_CHKTHIS(OQueryTableView,NULL);
694     OQueryTableWindow* pSourceWin = static_cast< OQueryTableWindow*>(jxdSource.pListBox->GetTabWin());
695     OQueryTableWindow* pDestWin = static_cast< OQueryTableWindow*>(jxdDest.pListBox->GetTabWin());
696 
697     String aSourceFieldName, aDestFieldName;
698     aSourceFieldName    = jxdSource.pListBox->GetEntryText(jxdSource.pEntry);
699     aDestFieldName      = jxdDest.pListBox->GetEntryText(jxdDest.pEntry);
700 
701     OTableConnection* pConn = GetTabConn(pSourceWin,pDestWin,true);
702     if ( !pConn )
703     {
704         // neues Daten-Objekt
705         OQueryTableConnectionData* pNewConnectionData = new OQueryTableConnectionData(pSourceWin->GetData(), pDestWin->GetData());
706         TTableConnectionData::value_type aNewConnectionData(pNewConnectionData);
707 
708         sal_uInt32          nSourceFieldIndex, nDestFieldIndex;
709         ETableFieldType eSourceFieldType, eDestFieldType;
710 
711         // Namen/Position/Typ der beiden betroffenen Felder besorgen ...
712         // Source
713 
714         nSourceFieldIndex = jxdSource.pListBox->GetModel()->GetAbsPos(jxdSource.pEntry);
715         eSourceFieldType = static_cast< OTableFieldInfo*>(jxdSource.pEntry->GetUserData())->GetKeyType();
716 
717         // Dest
718 
719         nDestFieldIndex = jxdDest.pListBox->GetModel()->GetAbsPos(jxdDest.pEntry);
720         eDestFieldType = static_cast< OTableFieldInfo*>(jxdDest.pEntry->GetUserData())->GetKeyType();
721 
722         // ... und setzen
723 
724         pNewConnectionData->SetFieldIndex(JTCS_FROM, nSourceFieldIndex);
725         pNewConnectionData->SetFieldIndex(JTCS_TO, nDestFieldIndex);
726 
727         pNewConnectionData->SetFieldType(JTCS_FROM, eSourceFieldType);
728         pNewConnectionData->SetFieldType(JTCS_TO, eDestFieldType);
729 
730         pNewConnectionData->AppendConnLine( aSourceFieldName,aDestFieldName );
731 
732         OQueryTableConnection aNewConnection(this, aNewConnectionData);
733         NotifyTabConnection(aNewConnection);
734             // wie immer bei NotifyTabConnection ist das Verwenden lokaler Variablen unkritisch, da sowieso eine Kopie erzeugt wird
735     }
736     else
737     {
738         // the connection could point on the other side
739         if(pConn->GetSourceWin() == pDestWin)
740         {
741             String aTmp(aSourceFieldName);
742             aSourceFieldName = aDestFieldName;
743             aDestFieldName = aTmp;
744         }
745 
746         pConn->GetData()->AppendConnLine( aSourceFieldName,aDestFieldName );
747 
748         connectionModified(this,pConn,sal_False);
749     }
750 }
751 // -----------------------------------------------------------------------------
752 void OQueryTableView::ConnDoubleClicked(OTableConnection* pConnection)
753 {
754     DBG_CHKTHIS(OQueryTableView,NULL);
755     if( openJoinDialog(this,pConnection->GetData(),sal_False) )
756     {
757         connectionModified(this,pConnection,sal_False);
758         SelectConn( pConnection );
759     }
760 }
761 // -----------------------------------------------------------------------------
762 void OQueryTableView::createNewConnection()
763 {
764     TTableConnectionData::value_type pData(new OQueryTableConnectionData());
765     if( openJoinDialog(this,pData,sal_True) )
766     {
767         OTableWindowMap* pMap = GetTabWinMap();
768         OQueryTableWindow* pSourceWin   = static_cast< OQueryTableWindow*>((*pMap)[pData->getReferencingTable()->GetWinName()]);
769         OQueryTableWindow* pDestWin     = static_cast< OQueryTableWindow*>((*pMap)[pData->getReferencedTable()->GetWinName()]);
770         // first we have to look if the this connection already exists
771         OTableConnection* pConn = GetTabConn(pSourceWin,pDestWin,true);
772         sal_Bool bNew = sal_True;
773         if ( pConn )
774         {
775             pConn->GetData()->CopyFrom( *pData );
776             bNew = sal_False;
777         }
778         else
779         {
780             // create a new conenction and append it
781             OQueryTableConnection* pQConn = new OQueryTableConnection(this, pData);
782             GetConnection(pQConn);
783             pConn = pQConn;
784         }
785         connectionModified(this,pConn,bNew);
786         if ( !bNew && pConn == GetSelectedConn() ) // our connection was selected before so we have to reselect it
787             SelectConn( pConn );
788     }
789 }
790 //------------------------------------------------------------------------------
791 bool OQueryTableView::RemoveConnection( OTableConnection* _pConnection,sal_Bool /*_bDelete*/ )
792 {
793     DBG_CHKTHIS(OQueryTableView,NULL);
794 
795     // we don't want that our connection will be deleted, we put it in the undo manager
796     bool bRet = OJoinTableView::RemoveConnection( _pConnection,sal_False);
797 
798     // add undo action
799     addUndoAction(  this,
800                     new OQueryDelTabConnUndoAction(this),
801                     static_cast< OQueryTableConnection*>(_pConnection),
802                     sal_True);
803     return bRet;
804 }
805 
806 //------------------------------------------------------------------------------
807 void OQueryTableView::KeyInput( const KeyEvent& rEvt )
808 {
809     DBG_CHKTHIS(OQueryTableView,NULL);
810     OJoinTableView::KeyInput( rEvt );
811 }
812 
813 //------------------------------------------------------------------------------
814 OQueryTableWindow* OQueryTableView::FindTable(const String& rAliasName)
815 {
816     DBG_CHKTHIS(OQueryTableView,NULL);
817     DBG_ASSERT(rAliasName.Len(), "OQueryTableView::FindTable : der AliasName sollte nicht leer sein !");
818         // (nicht dass es schadet, aber es ist sinnlos und weist vielleicht auf Fehler beim Aufrufer hin)
819     OTableWindowMap::const_iterator aIter = GetTabWinMap()->find(rAliasName);
820     if(aIter != GetTabWinMap()->end())
821         return static_cast<OQueryTableWindow*>(aIter->second);
822     return NULL;
823 }
824 
825 //------------------------------------------------------------------------------
826 sal_Bool OQueryTableView::FindTableFromField(const String& rFieldName, OTableFieldDescRef& rInfo, sal_uInt16& rCnt)
827 {
828     DBG_CHKTHIS(OQueryTableView,NULL);
829     rCnt = 0;
830     OTableWindowMap::const_iterator aIter = GetTabWinMap()->begin();
831     OTableWindowMap::const_iterator aEnd  = GetTabWinMap()->end();
832     for(;aIter != aEnd;++aIter)
833     {
834         if(static_cast<OQueryTableWindow*>(aIter->second)->ExistsField(rFieldName, rInfo))
835             ++rCnt;
836     }
837 
838     return rCnt == 1;
839 }
840 
841 //------------------------------------------------------------------------------
842 void OQueryTableView::RemoveTabWin(OTableWindow* pTabWin)
843 {
844     DBG_CHKTHIS(OQueryTableView,NULL);
845     DBG_ASSERT(pTabWin != NULL, "OQueryTableView::RemoveTabWin : Fenster sollte ungleich NULL sein !");
846 
847     // mein Parent brauche ich, da es vom Loeschen erfahren soll
848     OQueryDesignView* pParent = static_cast<OQueryDesignView*>(getDesignView());
849 
850     SfxUndoManager& rUndoMgr = m_pView->getController().GetUndoManager();
851     rUndoMgr.EnterListAction( String( ModuleRes(STR_QUERY_UNDO_TABWINDELETE) ), String() );
852 
853     // Undo-Action anlegen
854     OQueryTabWinDelUndoAct* pUndoAction = new OQueryTabWinDelUndoAct(this);
855     pUndoAction->SetTabWin(static_cast< OQueryTableWindow*>(pTabWin));
856 
857     // und Fenster verstecken
858     HideTabWin(static_cast< OQueryTableWindow*>(pTabWin), pUndoAction);
859 
860     // Undo Actions und Loeschen der Felder in SelectionBrowseBox
861     pParent->TableDeleted( static_cast< OQueryTableWindowData*>(pTabWin->GetData().get())->GetAliasName() );
862 
863     m_pView->getController().addUndoActionAndInvalidate( pUndoAction );
864     rUndoMgr.LeaveListAction();
865 
866     if (m_lnkTabWinsChangeHandler.IsSet())
867     {
868         TabWinsChangeNotification aHint(TabWinsChangeNotification::AT_REMOVED_WIN, static_cast< OQueryTableWindow*>(pTabWin)->GetAliasName());
869         m_lnkTabWinsChangeHandler.Call(&aHint);
870     }
871 
872     modified();
873     if ( m_pAccessible )
874         m_pAccessible->notifyAccessibleEvent(   AccessibleEventId::CHILD,
875                                                 makeAny(pTabWin->GetAccessible()),
876                                                 Any()
877                                                 );
878 }
879 
880 //------------------------------------------------------------------------
881 void OQueryTableView::EnsureVisible(const OTableWindow* pWin)
882 {
883     DBG_CHKTHIS(OQueryTableView,NULL);
884 
885     Invalidate(INVALIDATE_NOCHILDREN);
886     OJoinTableView::EnsureVisible(pWin);
887 }
888 
889 //------------------------------------------------------------------------
890 void OQueryTableView::GetConnection(OQueryTableConnection* pConn)
891 {
892     DBG_CHKTHIS(OQueryTableView,NULL);
893     // bei mir und dem Dokument einfuegen
894 
895     addConnection( pConn );
896     // invalidieren (damit es neu gezeichnet wird)
897     //  pConn->Invalidate();
898 }
899 
900 //------------------------------------------------------------------------
901 void OQueryTableView::DropConnection(OQueryTableConnection* pConn)
902 {
903     DBG_CHKTHIS(OQueryTableView,NULL);
904     // Selektion beachten
905     // bei mir und dem Dokument rausnehmen
906     RemoveConnection( pConn ,sal_False);
907 }
908 
909 //------------------------------------------------------------------------
910 void OQueryTableView::HideTabWin( OQueryTableWindow* pTabWin, OQueryTabWinUndoAct* pUndoAction )
911 {
912     DBG_CHKTHIS(OQueryTableView,NULL);
913     OTableWindowMap* pTabWins = GetTabWinMap();
914     DBG_ASSERT(pTabWins != NULL, "OQueryTableView::HideTabWin : habe keine TabWins !");
915 
916     if (pTabWin)
917     {
918         // Fenster
919         // die Position in seinen Daten speichern
920         getDesignView()->SaveTabWinUIConfig(pTabWin);
921             // (ich muss ueber das Parent gehen, da nur das die Position der Scrollbars kennt)
922         // dann aus der Liste der TabWins raus und verstecken
923         OTableWindowMap::iterator aIter = pTabWins->begin();
924         OTableWindowMap::iterator aEnd  = pTabWins->end();
925         for ( ;aIter != aEnd ; ++aIter )
926             if ( aIter->second == pTabWin )
927             {
928                 pTabWins->erase( aIter );
929                 break;
930             }
931 
932         pTabWin->Hide();    // nicht zerstoeren, steht im Undo!!
933 
934         // die Daten zum TabWin muessen auch aus meiner Verantwortung entlassen werden
935         TTableWindowData* pTabWinDataList = m_pView->getController().getTableWindowData();
936         pTabWinDataList->erase( ::std::remove(pTabWinDataList->begin(),pTabWinDataList->end(),pTabWin->GetData()),pTabWinDataList->end());
937             // NICHT loeschen, da ja das TabWin selber - das noch lebt - sie auch noch braucht
938             // Entweder geht es irgendwann wieder in meine Verantwortung ueber, (ueber ShowTabWin), dann fuege ich
939             // auch die Daten wieder ein, oder die Undo-Action, die im Augenblick die alleinige Verantwortung fuer das Fenster
940             // und dessen Daten hat, wird zestoert, dann loescht es beides
941 
942         if (m_pLastFocusTabWin == pTabWin)
943             m_pLastFocusTabWin = NULL;
944 
945         // Verbindungen, die zum Fenster gehoeren, einsammeln und der UndoAction uebergeben
946         sal_Int16 nCnt = 0;
947         const ::std::vector<OTableConnection*>* pTabConList = getTableConnections();
948         ::std::vector<OTableConnection*>::const_iterator aIter2 = pTabConList->begin();
949         for(;aIter2 != pTabConList->end();)// the end may change
950         {
951             OQueryTableConnection* pTmpEntry = static_cast<OQueryTableConnection*>(*aIter2);
952             OSL_ENSURE(pTmpEntry,"OQueryTableConnection is null!");
953             if( pTmpEntry->GetAliasName(JTCS_FROM) == pTabWin->GetAliasName() ||
954                 pTmpEntry->GetAliasName(JTCS_TO) == pTabWin->GetAliasName() )
955             {
956                 // add to undo list
957                 pUndoAction->InsertConnection(pTmpEntry);
958 
959                 // call base class because we append an undo action
960                 // but this time we are in a undo action list
961                 OJoinTableView::RemoveConnection(pTmpEntry,sal_False);
962                 aIter2 = pTabConList->begin();
963                 ++nCnt;
964             }
965             else
966                 ++aIter2;
967         }
968 
969         if (nCnt)
970             InvalidateConnections();
971 
972         m_pView->getController().InvalidateFeature(ID_BROWSER_ADDTABLE);
973 
974         // der UndoAction sagen, dass das Fenster (inklusive der Connections) jetzt in seinem Besitzt ist
975         pUndoAction->SetOwnership(sal_True);
976 
977         // damit habe ich das Doc natuerlich modifiziert
978         m_pView->getController().setModified( sal_True );
979         m_pView->getController().InvalidateFeature(SID_BROWSER_CLEAR_QUERY);
980     }
981 }
982 
983 //------------------------------------------------------------------------
984 sal_Bool OQueryTableView::ShowTabWin( OQueryTableWindow* pTabWin, OQueryTabWinUndoAct* pUndoAction,sal_Bool _bAppend )
985 {
986     DBG_CHKTHIS(OQueryTableView,NULL);
987 
988     sal_Bool bSuccess = sal_False;
989 
990     if (pTabWin)
991     {
992         if (pTabWin->Init())
993         {
994             TTableWindowData::value_type pData = pTabWin->GetData();
995             DBG_ASSERT(pData != NULL, "OQueryTableView::ShowTabWin : TabWin hat keine Daten !");
996             // Wenn die Daten schon PosSize haben, diese benutzen
997             if (pData->HasPosition() && pData->HasSize())
998             {
999                 Size aSize(CalcZoom(pData->GetSize().Width()),CalcZoom(pData->GetSize().Height()));
1000                 pTabWin->SetPosSizePixel(pData->GetPosition(), aSize);
1001             }
1002             else
1003                 // ansonsten selber eine Default-Position ermitteln
1004                 SetDefaultTabWinPosSize(pTabWin);
1005 
1006             // Fenster zeigen und in Liste eintragen
1007             ::rtl::OUString sName = static_cast< OQueryTableWindowData*>(pData.get())->GetAliasName();
1008             OSL_ENSURE(GetTabWinMap()->find(sName) == GetTabWinMap()->end(),"Alias name already in list!");
1009             GetTabWinMap()->insert(OTableWindowMap::value_type(sName,pTabWin));
1010 
1011             pTabWin->Show();
1012 
1013             pTabWin->Update();
1014                 // Das Update ist notwendig, damit die Connections an dem Fenster richtig gezeichnet werden. Klingt absurd,
1015                 // ich weiss. Aber die Listbox haelt sich intern ein Member, was bei ersten Zeichnen (nachdem die Listbox im Init
1016                 // gerade neu gefuellt wurde) initialisiert wird, und genau dieses Member wird irgendwann benoetigt fuer
1017                 // GetEntryPos, und dieses wiederum von der Connection, wenn sie ihren Ansatzpunkt am Fenster feststellen will.
1018 
1019             // die Connections
1020             ::std::vector<OTableConnection*>* pTableCon = pUndoAction->GetTabConnList();
1021             ::std::vector<OTableConnection*>::iterator aIter = pTableCon->begin();
1022             ::std::vector<OTableConnection*>::iterator aEnd = pTableCon->end();
1023 
1024             for(;aIter != aEnd;++aIter)
1025                 addConnection(*aIter); // add all connections from the undo action
1026 
1027             // each connection should invalidated inside addConnection so we don't need this here any longer
1028 //          if ( !pOwnList->empty() )
1029 //              InvalidateConnections();
1030             pTableCon->clear();
1031 
1032             // und die Daten des Fensters ebenfalls in Liste (des Docs)
1033             if(_bAppend)
1034                 m_pView->getController().getTableWindowData()->push_back(pTabWin->GetData());
1035 
1036             m_pView->getController().InvalidateFeature(ID_BROWSER_ADDTABLE);
1037 
1038             // und der UndoAction sagen, dass das Fenster jetzt meine ist ...
1039             pUndoAction->SetOwnership(sal_False);
1040 
1041             bSuccess = sal_True;
1042         }
1043         else
1044         {
1045             //////////////////////////////////////////////////////////////////
1046             // Initialisierung fehlgeschlagen
1047             // (z.B. wenn Verbindung zur Datenbank in diesem Augenblick unterbrochen worden ist)
1048             pTabWin->clearListBox();
1049             delete pTabWin;
1050         }
1051     }
1052 
1053     // damit habe ich das Doc natuerlich modifiziert
1054     if(!m_pView->getController().isReadOnly())
1055         m_pView->getController().setModified( sal_True );
1056 
1057     m_pView->getController().InvalidateFeature(SID_BROWSER_CLEAR_QUERY);
1058 
1059     return bSuccess;
1060 }
1061 //------------------------------------------------------------------------
1062 void OQueryTableView::InsertField(const OTableFieldDescRef& rInfo)
1063 {
1064     DBG_CHKTHIS(OQueryTableView,NULL);
1065     DBG_ASSERT(getDesignView() != NULL, "OQueryTableView::InsertField : habe kein Parent !");
1066     static_cast<OQueryDesignView*>(getDesignView())->InsertField(rInfo);
1067 }
1068 //------------------------------------------------------------------------------
1069 sal_Bool OQueryTableView::ExistsAVisitedConn(const OQueryTableWindow* pFrom) const
1070 {
1071     DBG_CHKTHIS(OQueryTableView,NULL);
1072     const ::std::vector<OTableConnection*>* pList = getTableConnections();
1073     if (pList)
1074     {
1075         ::std::vector<OTableConnection*>::const_iterator aIter = pList->begin();
1076         ::std::vector<OTableConnection*>::const_iterator aEnd = pList->end();
1077         for(;aIter != aEnd;++aIter)
1078         {
1079             OQueryTableConnection* pTemp = static_cast<OQueryTableConnection*>(*aIter);
1080             if (pTemp->IsVisited() &&
1081                 (pFrom == static_cast< OQueryTableWindow*>(pTemp->GetSourceWin()) || pFrom == static_cast< OQueryTableWindow*>(pTemp->GetDestWin())))
1082                 return pTemp != NULL;
1083         }
1084     }
1085 
1086     return sal_False;
1087 }
1088 // -----------------------------------------------------------------------------
1089 void OQueryTableView::onNoColumns_throw()
1090 {
1091     String sError( ModuleRes( STR_STATEMENT_WITHOUT_RESULT_SET ) );
1092     ::dbtools::throwSQLException( sError, ::dbtools::SQL_GENERAL_ERROR, NULL );
1093 }
1094 //------------------------------------------------------------------------------
1095 bool OQueryTableView::supressCrossNaturalJoin(const TTableConnectionData::value_type& _pData) const
1096 {
1097     OQueryTableConnectionData* pQueryData = static_cast<OQueryTableConnectionData*>(_pData.get());
1098     return pQueryData && (pQueryData->GetJoinType() == CROSS_JOIN);
1099 }
1100 // -----------------------------------------------------------------------------
1101