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