diff options
Diffstat (limited to 'dbaccess/source/ui/querydesign/QueryTableView.cxx')
-rw-r--r-- | dbaccess/source/ui/querydesign/QueryTableView.cxx | 1222 |
1 files changed, 1222 insertions, 0 deletions
diff --git a/dbaccess/source/ui/querydesign/QueryTableView.cxx b/dbaccess/source/ui/querydesign/QueryTableView.cxx new file mode 100644 index 000000000000..7c45106f48b6 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryTableView.cxx @@ -0,0 +1,1222 @@ +/************************************************************************* + * + * $RCSfile: QueryTableView.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: oj $ $Date: 2001-02-05 09:21:16 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the License); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an AS IS basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef DBAUI_QUERYTABLEVIEW_HXX +#include "QueryTableView.hxx" +#endif +#ifndef DBAUI_TABLEFIELDINFO_HXX +#include "TableFieldInfo.hxx" +#endif +#ifndef DBAUI_TABLEFIELDDESC_HXX +#include "TableFieldDescription.hxx" +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#include "dbaccess_helpid.hrc" +#ifndef DBAUI_QUERY_TABLEWINDOW_HXX +#include "QTableWindow.hxx" +#endif +#ifndef DBAUI_QUERYTABLECONNECTION_HXX +#include "QTableConnection.hxx" +#endif +#ifndef DBAUI_QTABLECONNECTIONDATA_HXX +#include "QTableConnectionData.hxx" +#endif +#ifndef DBAUI_QUERYDESIGNVIEW_HXX +#include "QueryDesignView.hxx" +#endif +#ifndef DBAUI_QUERYCONTROLLER_HXX +#include "querycontroller.hxx" +#endif +#ifndef DBAUI_OQUERYMOVETABWINUNDOACT_HXX +#include "QueryMoveTabWinUndoAct.hxx" +#endif +#ifndef DBAUI_QUERYADDTABCONNUNDOACTION_HXX +#include "QueryAddTabConnUndoAction.hxx" +#endif +#ifndef DBAUI_QUERYTABWINSHOWUNDOACT_HXX +#include "QueryTabWinShowUndoAct.hxx" +#endif +#ifndef DBAUI_QUERYSIZETABWINUNDOACT_HXX +#include "QuerySizeTabWinUndoAct.hxx" +#endif +#ifndef DBACCESS_UI_BROWSER_ID_HXX +#include "browserids.hxx" +#endif +#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XKEYSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_KEYTYPE_HPP_ +#include <com/sun/star/sdbcx/KeyType.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_ +#include <com/sun/star/container/XIndexAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef DBACCESS_SHARED_DBUSTRINGS_HRC +#include "dbustrings.hrc" +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef DBAUI_QUERYDLG_HXX +#include "querydlg.hxx" +#endif +#ifndef DBAUI_JOINEXCHANGE_HXX +#include "JoinExchange.hxx" +#endif + +using namespace dbaui; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; + +TYPEINIT1(OQueryTableView, OJoinTableView); + +//------------------------------------------------------------------------------ +::rtl::OUString ConvertAlias(const ::rtl::OUString& _rName) +{ + if (!_rName.getLength()) + return _rName; + + String rName(_rName); + + const sal_Unicode* pStr = rName.GetBuffer(); + sal_Bool bValid(!((*pStr >= 48) && (*pStr <= 57))); // keine Zahl am Anfang + + String aTmp; + if (bValid) + aTmp = rName; + + for (sal_Int32 i=0; i < rName.Len() && *pStr;i++, pStr++ ){ + if ( ((*pStr >= 97) && (*pStr <= 122)) ||((*pStr >= 65) && (*pStr <= 90)) || + ((*pStr >= 48) && (*pStr <= 57)) || *pStr == '_' ) + ; + else + aTmp.SearchAndReplace(*pStr,'_'); + + } + + return aTmp; +} + +//================================================================== +// class OQueryTableView +//================================================================== +DBG_NAME(OQueryTableView); +//------------------------------------------------------------------------ +OQueryTableView::OQueryTableView( Window* pParent,OQueryDesignView* pView) + : OJoinTableView( pParent,pView) +{ + DBG_CTOR(OQueryTableView,NULL); + SetHelpId(HID_CTL_QRYDGNTAB); + EnableDrop(); +} + +//------------------------------------------------------------------------ +OQueryTableView::~OQueryTableView() +{ + DBG_DTOR(OQueryTableView,NULL); + ////////////////////////////////////////////////////////////////////// + // Listen loeschen + OTableWindowMapIterator aIter = GetTabWinMap()->begin(); + for(;aIter != GetTabWinMap()->end();++aIter) + delete aIter->second; + + GetTabWinMap()->clear(); + + ::std::vector<OTableConnection*>::iterator aIter2 = GetTabConnList()->begin(); + for(;aIter2 != GetTabConnList()->end();++aIter2) + delete *aIter2; + + // den Undo-Manager des Dokuments leeren (da die UndoActions sich eventuell TabWins von mir halten, das gibt sonst eine + // Assertion in Window::~Window) + m_pView->getController()->getUndoMgr()->Clear(); +} + +//------------------------------------------------------------------------ +sal_uInt16 OQueryTableView::CountTableAlias(const String& rName, sal_uInt16& rMax) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + sal_uInt16 nRet = 0; + + OTableWindowMapIterator aIter = GetTabWinMap()->find(rName); + while(aIter != GetTabWinMap()->end()) + { + OTableWindow* pWin = aIter->second; + + String aNewName; + aNewName = rName; + aNewName += '_'; + aNewName += String::CreateFromInt32(++nRet); + + aIter = GetTabWinMap()->find(aNewName); + } + + rMax = nRet; + + return nRet; +} + + +//------------------------------------------------------------------------ +void OQueryTableView::TabWinMoved(OTableWindow* pWhich, const Point& ptOldPosition) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + OJoinTableView::TabWinMoved(pWhich, ptOldPosition); + + SfxUndoAction* pUndoAction = new OQueryMoveTabWinUndoAct(this, ptOldPosition, static_cast< OQueryTableWindow*>(pWhich)); + m_pView->getController()->getUndoMgr()->AddUndoAction(pUndoAction); +} + +//------------------------------------------------------------------------ +void OQueryTableView::TabWinSized(OTableWindow* pWhich, const Point& ptOldPosition, const Size& szOldSize) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + OJoinTableView::TabWinSized(pWhich, ptOldPosition, szOldSize); + + SfxUndoAction* pUndoAction = new OQuerySizeTabWinUndoAct(this, ptOldPosition, szOldSize, static_cast< OQueryTableWindow*>(pWhich)); + m_pView->getController()->getUndoMgr()->AddUndoAction(pUndoAction); +} + +//------------------------------------------------------------------------ +void OQueryTableView::ReSync() +{ + DBG_CHKTHIS(OQueryTableView,NULL); + ::std::vector< OTableWindowData*>* pTabWinDataList = m_pView->getController()->getTableWindowData(); + DBG_ASSERT((GetTabConnList()->size()==0) && (GetTabWinMap()->size()==0), + "vor OQueryTableView::ReSync() bitte ClearAll aufrufen !"); + + // ich brauche eine Sammlung aller Fensternamen, deren Anlegen schief geht, damit ich die entsprechenden Connections + // gar nicht erst anlege + ::std::vector<String> arrInvalidTables; + + ::std::vector< OTableWindowData*>::reverse_iterator aIter = pTabWinDataList->rbegin(); + // Fenster kreieren und einfuegen + + for(;aIter != pTabWinDataList->rend();++aIter) + { + OQueryTableWindowData* pData = static_cast<OQueryTableWindowData*>(*aIter); + OQueryTableWindow* pTabWin = new OQueryTableWindow(this, pData); + + // ich gehe jetzt NICHT ueber ShowTabWin, da dieses die Daten des Fensters in die Liste des Docs einfuegt, was + // schlecht waere, denn genau von dort hole ich sie ja gerade + // also Schritt fuer Schritt + if (!pTabWin->Init()) + { + // das Initialisieren ging schief, dass heisst, dieses TabWin steht nicht zur Verfuegung, also muss ich es inklusive + // seiner Daten am Dokument aufraeumen + delete pTabWin; + arrInvalidTables.push_back(pData->GetAliasName()); + + pTabWinDataList->erase( ::std::find(pTabWinDataList->begin(),pTabWinDataList->end(),*aIter) ); + delete pData; + continue; + } + + (*GetTabWinMap())[pData->GetAliasName()] = pTabWin; // am Anfang einfuegen, da ich die DataList ja rueckwaerts durchlaufe + // wenn in den Daten keine Position oder Groesse steht -> Default + if (!pData->HasPosition() && !pData->HasSize()) + SetDefaultTabWinPosSize(pTabWin); + + pTabWin->Show(); + } + + // Verbindungen einfuegen + ::std::vector< OTableConnectionData*>* pTabConnDataList = m_pView->getController()->getTableConnectionData(); + ::std::vector< OTableConnectionData*>::reverse_iterator aConIter = pTabConnDataList->rbegin(); + + for(;aConIter != pTabConnDataList->rend();++aConIter) + { + OQueryTableConnectionData* pTabConnData = static_cast<OQueryTableConnectionData*>(*aConIter); + + // gibt es die beiden Tabellen zur Connection ? + String strTabExistenceTest = pTabConnData->GetSourceWinName(); + sal_Bool bInvalid = ::std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end(); + strTabExistenceTest = pTabConnData->GetDestWinName(); + bInvalid |= ::std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end(); + + if (bInvalid) + { // nein -> Pech gehabt, die Connection faellt weg + pTabConnDataList->erase( ::std::find(pTabConnDataList->begin(),pTabConnDataList->end(),*aConIter) ); + delete pTabConnData; + continue; + } + + GetTabConnList()->push_back(new OQueryTableConnection(this, pTabConnData)); + } +} + +//------------------------------------------------------------------------ +void OQueryTableView::ClearAll() +{ + DBG_CHKTHIS(OQueryTableView,NULL); + OJoinTableView::ClearAll(); + + SetUpdateMode(sal_True); + m_pView->getController()->setModified(sal_True); +} + +//------------------------------------------------------------------------------ +void OQueryTableView::NotifyTabConnection(const OQueryTableConnection& rNewConn, sal_Bool _bCreateUndoAction) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + // erst mal schauen, ob ich diese Connection schon habe + OQueryTableConnection* pTabConn = NULL; + ::std::vector<OTableConnection*>::iterator aIter = ::std::find(GetTabConnList()->begin(),GetTabConnList()->end(),static_cast<const OTableConnection*>(&rNewConn)); + if(aIter == GetTabConnList()->end()) + { + aIter = GetTabConnList()->begin(); + for(;aIter != GetTabConnList()->end();++aIter) + { + if(*static_cast<OQueryTableConnection*>(*aIter) == rNewConn) + { + pTabConn = static_cast<OQueryTableConnection*>(*aIter); + break; + } + } + } + else + pTabConn = static_cast<OQueryTableConnection*>(*aIter); + // nein -> einfuegen + if (pTabConn == NULL) + { + // die neuen Daten ... + OQueryTableConnectionData* pNewData = static_cast< OQueryTableConnectionData*>(rNewConn.GetData()->NewInstance()); + pNewData->CopyFrom(*rNewConn.GetData()); + // ... an das Dokument anhaengen + m_pView->getController()->getTableConnectionData()->push_back(pNewData); + // ... und an eine neue OQueryTableConnection-Instanz haengen, die ich mir gleich merke + OQueryTableConnection* pNewConn = new OQueryTableConnection(this, pNewData); + GetTabConnList()->push_back(pNewConn); + + // Modified-Flag + m_pView->getController()->setModified(sal_True); + + // eine Undo-Action fuer die Connection + if (_bCreateUndoAction) + { + OQueryTabConnUndoAction* pUndoAction = new OQueryAddTabConnUndoAction(this); + pUndoAction->SetOwnership(sal_False); + pUndoAction->SetConnection(pNewConn); + m_pView->getController()->getUndoMgr()->AddUndoAction(pUndoAction); + } + + // und neu zeichnen + pNewConn->RecalcLines(); + // fuer das unten folgende Invalidate muss ich dieser neuen Connection erst mal die Moeglichkeit geben, + // ihr BoundingRect zu ermitteln + pNewConn->Invalidate(); + } +} + +//------------------------------------------------------------------------------ +void OQueryTableView::AddTabWin(const String& strDatabase, const String& strTableName, sal_Bool bNewTable) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + // das ist die aus der Basisklasse geerbte Methode, die fuehre ich auf die an meinem Parent zurueck, die mir eventuell einen + // Alias dazu bastelt und das an mein anderes AddTabWin weiterreicht + + // leider ist strTableName voll qualifiziert, das OQueryDesignView erwartet aber einen String, der + // nur aus Schema und Tabelle besteht und keinen Katalog enthaelt. + ::rtl::OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents(m_pView->getController()->getConnection()->getMetaData(), + strDatabase, + sCatalog, + sSchema, + sTable); + String sRealName(sSchema); + if (sRealName.Len()) + sRealName+= '.'; + sRealName += sTable.getStr(); + + AddTabWin(strDatabase, sRealName, ConvertAlias(sTable.getStr()), bNewTable); +} +// ----------------------------------------------------------------------------- +// find the table which has a foreign key with this referencedTable name +Reference<XPropertySet> getKeyReferencedTo(const Reference<XKeysSupplier>& _rxKeys,const ::rtl::OUString& _rReferencedTable) +{ + if(!_rxKeys.is()) + return Reference<XPropertySet>(); + + Reference< XIndexAccess> xKeyIndex = _rxKeys->getKeys(); + // search the one and only primary key + for(sal_Int32 i=0;i< xKeyIndex->getCount();++i) + { + Reference<XPropertySet> xKey; + xKeyIndex->getByIndex(i) >>= xKey; + if(xKey.is()) + { + sal_Int32 nKeyType = 0; + xKey->getPropertyValue(PROPERTY_TYPE) >>= nKeyType; + if(KeyType::FOREIGN == nKeyType) + { + ::rtl::OUString sReferencedTable; + xKey->getPropertyValue(PROPERTY_REFERENCEDTABLE) >>= sReferencedTable; + // TODO check case + if(sReferencedTable == _rReferencedTable) + return xKey; + } + } + } + return Reference<XPropertySet>(); +} +// ----------------------------------------------------------------------------- +sal_Bool isColumnInKeyType(const Reference<XKeysSupplier>& _rxKeys,const ::rtl::OUString& _rColumnName,sal_Int32 _nKeyType) +{ + sal_Bool bReturn = sal_False; + if(_rxKeys.is()) + { + Reference< XIndexAccess> xKeyIndex = _rxKeys->getKeys(); + Reference<XColumnsSupplier> xColumnsSupplier; + // search the one and only primary key + for(sal_Int32 i=0;i< xKeyIndex->getCount();++i) + { + Reference<XPropertySet> xProp; + xKeyIndex->getByIndex(i) >>= xProp; + if(xProp.is()) + { + sal_Int32 nKeyType = 0; + xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType; + if(_nKeyType == nKeyType) + { + xColumnsSupplier = Reference<XColumnsSupplier>(xProp,UNO_QUERY); + if(xColumnsSupplier.is()) + { + Reference<XNameAccess> xColumns = xColumnsSupplier->getColumns(); + if(xColumns.is() && xColumns->hasByName(_rColumnName)) + { + bReturn = sal_True; + break; + } + } + } + } + } + } + return bReturn; +} +// ----------------------------------------------------------------------------- +void OQueryTableView::addConnections(const OQueryTableWindow* _pSource,const OQueryTableWindow* _pDest,const Reference<XNameAccess>& _rxSourceForeignKeyColumns) +{ + // we found a table in our view where we can insert some connections + // the key columns have a property called RelatedColumn + // OQueryTableConnectionData aufbauen + OQueryTableConnectionData aNewConnData( _pSource->GetTableName(), _pDest->GetTableName(), + _pSource->GetAliasName(), _pDest->GetAliasName()); + + Reference<XKeysSupplier> xReferencedKeys(_pDest->GetTable(),UNO_QUERY); + ::rtl::OUString sRelatedColumn; + + // iterate through all foreignkey columns to create the connections + Sequence< ::rtl::OUString> aElements(_rxSourceForeignKeyColumns->getElementNames()); + const ::rtl::OUString* pBegin = aElements.getConstArray(); + const ::rtl::OUString* pEnd = pBegin + aElements.getLength(); + for(sal_Int32 i=0;pBegin != pEnd;++pBegin,++i) + { + Reference<XPropertySet> xColumn; + _rxSourceForeignKeyColumns->getByName(*pBegin) >>= xColumn; + + aNewConnData.SetFieldType(JTCS_FROM,TAB_NORMAL_FIELD); + + xColumn->getPropertyValue(PROPERTY_RELATEDCOLUMN) >>= sRelatedColumn; + aNewConnData.SetFieldType(JTCS_TO,isColumnInKeyType(xReferencedKeys,sRelatedColumn,KeyType::PRIMARY) ? TAB_PRIMARY_FIELD : TAB_NORMAL_FIELD); + + { + Sequence< sal_Int16> aFind(::comphelper::findValue(_pSource->GetOriginalColumns()->getElementNames(),*pBegin,sal_True)); + if(aFind.getLength()) + aNewConnData.SetFieldIndex(JTCS_FROM,aFind[0]+1); + else + OSL_ENSURE(0,"Column not found!"); + } + // get the position inside the tabe + Reference<XNameAccess> xRefColumns = _pDest->GetOriginalColumns(); + if(xRefColumns.is()) + { + Sequence< sal_Int16> aFind(::comphelper::findValue(xRefColumns->getElementNames(),sRelatedColumn,sal_True)); + if(aFind.getLength()) + aNewConnData.SetFieldIndex(JTCS_TO,aFind[0]+1); + else + OSL_ENSURE(0,"Column not found!"); + } + aNewConnData.AppendConnLine(*pBegin,sRelatedColumn); + + // dann die Conn selber dazu + OQueryTableConnection aNewConn(this, &aNewConnData); + // der Verweis auf die lokale Variable ist unkritisch, da NotifyQueryTabConn eine neue Kopie anlegt + // und mir hinzufuegen (wenn nicht schon existent) + NotifyTabConnection(aNewConn, sal_False); + // don't create an Undo-Action for the new connection : the connection is + // covered by the Undo-Action for the tabwin, as the "Undo the insert" will + // automatically remove all connections adjacent to the win. + // (Because of this automatism we would have an ownerhsip ambiguity for + // the connection data if we would insert the conn-Undo-Action) + // FS - 21.10.99 - 69183 + } +} +//------------------------------------------------------------------------------ +void OQueryTableView::AddTabWin(const String& _rComposedName, const String& strTableName, const String& strAlias, sal_Bool bNewTable) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + DBG_ASSERT(strTableName.Len() || strAlias.Len(), "OQueryTableView::AddTabWin : kein Tabellen- und kein Aliasname !"); + // wenn der Tabellenname nicht gesetzt ist, steht das fuer ein Dummy-Fenster, das braucht aber wenigstens einen Alias-Namen + + String strDBName = _rComposedName; + + // neue Datenstruktur erzeugen + OQueryTableWindowData* pNewTabWinData = new OQueryTableWindowData(strDBName, strTableName, strAlias); + // die TabWinData brauche ich nicht in die entsprechende Liste der DocShell eintragen, das macht ShowTabWin + + // neues Fenster erzeugen + OQueryTableWindow* pNewTabWin = new OQueryTableWindow(this, pNewTabWinData); + // das Init kann ich hier weglassen, da das in ShowTabWin passiert + + // Neue UndoAction + OQueryTabWinShowUndoAct* pUndoAction = new OQueryTabWinShowUndoAct(this); + pUndoAction->SetTabWin(pNewTabWin); // Fenster + sal_Bool bSuccess = ShowTabWin(pNewTabWin, pUndoAction); + + // Relationen zwischen den einzelnen Tabellen anzeigen + OTableWindowMap* pTabWins = GetTabWinMap(); + if(bNewTable && pTabWins->size() && strTableName.Len()) + { + Reference<XConnection> xCon = m_pView->getController()->getConnection(); + Reference<XTablesSupplier> xSup(xCon,UNO_QUERY); + Reference<XNameAccess> xTables = xSup->getTables(); + Reference<XPropertySet> xTable; + + if(xTables->hasByName(strTableName) && (xTables->getByName(strTableName) >>= xTable) && xTable.is() ) + { + ////////////////////////////////////////////////////////////////////// + // find relations between the table an the tables already inserted + Reference<XKeysSupplier> xKeys(xTable,UNO_QUERY); + Reference<XNameAccess> xFKeyColumns; + ::rtl::OUString aReferencedTable; + if(xKeys.is()) + { + Reference< XIndexAccess> xKeyIndex = xKeys->getKeys(); + Reference<XColumnsSupplier> xColumnsSupplier; + for(sal_Int32 i=0;i< xKeyIndex->getCount();++i) + { + Reference<XPropertySet> xProp; + xKeyIndex->getByIndex(i) >>= xProp; + sal_Int32 nKeyType = 0; + xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType; + xColumnsSupplier = Reference<XColumnsSupplier>(xProp,UNO_QUERY); + OSL_ENSURE(xColumnsSupplier.is(),"Key isn't a column supplier"); + xFKeyColumns = xColumnsSupplier->getColumns(); + OSL_ENSURE(xFKeyColumns.is(),"No Key columns available!"); + + if(KeyType::FOREIGN == nKeyType) + { // our new table has a foreign key + // so look if the referenced table is already in our list + xProp->getPropertyValue(PROPERTY_REFERENCEDTABLE) >>= aReferencedTable; + OSL_ENSURE(aReferencedTable.getLength(),"Foreign key without referencedTableName"); + + OTableWindowMap::const_iterator aIter = pTabWins->find(aReferencedTable); + if(aIter == pTabWins->end()) + { + for(aIter = pTabWins->begin();aIter != pTabWins->end();++aIter) + { + OQueryTableWindow* pTabWinTmp = static_cast<OQueryTableWindow*>(aIter->second); + OSL_ENSURE(pTabWinTmp,"TableWindow is null!"); + if(pTabWinTmp != pNewTabWin && pTabWinTmp->GetComposedName() == aReferencedTable.getStr()) + break; + } + } + if(aIter != pTabWins->end()) + addConnections(pNewTabWin,static_cast<OQueryTableWindow*>(aIter->second),xFKeyColumns); + } + else if(KeyType::PRIMARY == nKeyType) + { + // we have a primary key so look in our list if there exsits a key which this is refered to + OTableWindowMap::const_iterator aIter = pTabWins->begin(); + for(;aIter != pTabWins->end();++aIter) + { + OQueryTableWindow* pTabWinTmp = static_cast<OQueryTableWindow*>(aIter->second); + if(pTabWinTmp != pNewTabWin) + { + OSL_ENSURE(pTabWinTmp,"TableWindow is null!"); + Reference<XPropertySet> xFKKey = getKeyReferencedTo(Reference<XKeysSupplier>(pTabWinTmp->GetTable(),UNO_QUERY),pNewTabWin->GetComposedName()); + if(xFKKey.is()) + { + Reference<XColumnsSupplier> xFKColumnsSupplier = Reference<XColumnsSupplier>(xFKKey,UNO_QUERY); + OSL_ENSURE(xFKColumnsSupplier.is(),"Key isn't a column supplier"); + Reference<XNameAccess> xTColumns = xFKColumnsSupplier->getColumns(); + OSL_ENSURE(xTColumns.is(),"No Key columns available!"); + addConnections(pTabWinTmp,pNewTabWin,xTColumns); + } + } + } + } + } + + } + } + } + + // mein Parent brauche ich, da es vom Loeschen erfahren soll + m_pView->getController()->setModified(sal_True); + + m_pView->getController()->getUndoMgr()->AddUndoAction( pUndoAction ); + + if (bSuccess && m_lnkTabWinsChangeHandler.IsSet()) + { + TabWinsChangeNotification aHint(TabWinsChangeNotification::AT_ADDED_WIN, pNewTabWin->GetAliasName()); + m_lnkTabWinsChangeHandler.Call(&aHint); + } + + m_pView->getController()->InvalidateFeature(ID_BROWSER_UNDORECORD); + m_pView->getController()->InvalidateFeature(ID_BROWSER_REDO); + // GetViewShell()->GetViewShell()->UIFeatureChanged(); +} +//------------------------------------------------------------------------ +void OQueryTableView::AddConnection(const OJoinExchangeData& jxdSource, const OJoinExchangeData& jxdDest) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + OQueryTableWindow* pSourceWin = static_cast< OQueryTableWindow*>(jxdSource.pListBox->GetTabWin()); + OQueryTableWindow* pDestWin = static_cast< OQueryTableWindow*>(jxdDest.pListBox->GetTabWin()); + + String aSourceFieldName, aDestFieldName; + aSourceFieldName = jxdSource.pListBox->GetEntryText(jxdSource.pEntry); + aDestFieldName = jxdDest.pListBox->GetEntryText(jxdDest.pEntry); + + OTableConnection* pConn = GetTabConn(pSourceWin,pDestWin); + if(!pConn) + { + // neues Daten-Objekt + OQueryTableConnectionData aNewConnectionData(pSourceWin->GetTableName(), pDestWin->GetTableName(), pSourceWin->GetAliasName(), pDestWin->GetAliasName()); + + sal_uInt32 nSourceFieldIndex, nDestFieldIndex; + ETableFieldType eSourceFieldType, eDestFieldType; + + // Namen/Position/Typ der beiden betroffenen Felder besorgen ... + // Source + + nSourceFieldIndex = jxdSource.pListBox->GetModel()->GetAbsPos(jxdSource.pEntry); + eSourceFieldType = static_cast< OTableFieldInfo*>(jxdSource.pEntry->GetUserData())->GetKeyType(); + + // Dest + + nDestFieldIndex = jxdDest.pListBox->GetModel()->GetAbsPos(jxdDest.pEntry); + eDestFieldType = static_cast< OTableFieldInfo*>(jxdDest.pEntry->GetUserData())->GetKeyType(); + + // ... und setzen + + aNewConnectionData.SetFieldIndex(JTCS_FROM, nSourceFieldIndex); + aNewConnectionData.SetFieldIndex(JTCS_TO, nDestFieldIndex); + + aNewConnectionData.SetFieldType(JTCS_FROM, eSourceFieldType); + aNewConnectionData.SetFieldType(JTCS_TO, eDestFieldType); + + aNewConnectionData.AppendConnLine( aSourceFieldName,aDestFieldName ); + + OQueryTableConnection aNewConnection(this, &aNewConnectionData); + NotifyTabConnection(aNewConnection); + // wie immer bei NotifyTabConnection ist das Verwenden lokaler Variablen unkritisch, da sowieso eine Kopie erzeugt wird + } + else + { + // the connection could point on the other side + if(pConn->GetSourceWin() == pDestWin) + { + String aTmp(aSourceFieldName); + aSourceFieldName = aDestFieldName; + aDestFieldName = aTmp; + } + + pConn->GetData()->AppendConnLine( aSourceFieldName,aDestFieldName ); + pConn->UpdateLineList(); + // Modified-Flag + m_pView->getController()->setModified(sal_True); + + // eine Undo-Action fuer die Connection + OQueryTabConnUndoAction* pUndoAction = new OQueryAddTabConnUndoAction(this); + pUndoAction->SetOwnership(sal_False); + pUndoAction->SetConnection(static_cast< OQueryTableConnection*>(pConn)); + m_pView->getController()->getUndoMgr()->AddUndoAction(pUndoAction); + + // und neu zeichnen + pConn->RecalcLines(); + // fuer das unten folgende Invalidate muss ich dieser neuen Connection erst mal die Moeglichkeit geben, + // ihr BoundingRect zu ermitteln + pConn->Invalidate(); + } +} + + +//------------------------------------------------------------------------ +void OQueryTableView::ConnDoubleClicked(OTableConnection* pConnection) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + DBG_ASSERT(pConnection->ISA(OQueryTableConnection), "OQueryTableView::ConnDoubleClicked : pConnection hat falschen Typ"); + // da ich nur solche selber verwende, duerfen auch nur solche hier ankommen + + DlgQryJoin aDlg(this,static_cast< OQueryTableConnectionData*>(pConnection->GetData()),m_pView->getController()->getConnection()->getMetaData()); + aDlg.Execute(); + if(static_cast< OQueryTableConnectionData*>(pConnection->GetData())->GetJoinType() != aDlg.GetJoinType()) + { + static_cast< OQueryTableConnectionData*>(pConnection->GetData())->SetJoinType(aDlg.GetJoinType()); + m_pView->getController()->setModified(sal_True); + } +/* + String strMessage(ModuleRes(RID_STR_CONNECTION_DATA)); + strMessage.SearchAndReplace("$alias1$", static_cast< OQueryTableConnection*>(pConnection)->GetAliasName(JTCS_FROM)); + strMessage.SearchAndReplace("$alias2$", static_cast< OQueryTableConnection*>(pConnection)->GetAliasName(JTCS_TO)); + strMessage.SearchAndReplace("$field1$", static_cast< OQueryTableConnection*>(pConnection)->GetFieldName(JTCS_FROM)); + strMessage.SearchAndReplace("$field2$", static_cast< OQueryTableConnection*>(pConnection)->GetFieldName(JTCS_TO)); + + InfoBox(this, strMessage).Execute(); +*/ +} + +//------------------------------------------------------------------------------ +sal_Bool OQueryTableView::RemoveConnection( OTableConnection* pConn ) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + DBG_ASSERT(pConn->ISA(OQueryTableConnection), "OQueryTableView::RemoveConnection : Connection ist vom falschen Typ !"); + // NICHT die Basisklasse erledigen lassen (die loescht die Connection hart, ich will sie aber ans Undo uebergeben) + DropConnection(static_cast< OQueryTableConnection*>(pConn)); + + // eine Undo-Action + OQueryTabConnUndoAction* pUndoAction = new OQueryDelTabConnUndoAction(this); + pUndoAction->SetOwnership(sal_True); + pUndoAction->SetConnection(static_cast< OQueryTableConnection*>(pConn)); + m_pView->getController()->getUndoMgr()->AddUndoAction(pUndoAction); + + // modified-Flag + m_pView->getController()->setModified(sal_True); + return sal_True; +} + +//------------------------------------------------------------------------------ +void OQueryTableView::KeyInput( const KeyEvent& rEvt ) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + OJoinTableView::KeyInput( rEvt ); +} + +//------------------------------------------------------------------------------ +OQueryTableWindow* OQueryTableView::FindTable(const String& rAliasName) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + DBG_ASSERT(rAliasName.Len(), "OQueryTableView::FindTable : der AliasName sollte nicht leer sein !"); + // (nicht dass es schadet, aber es ist sinnlos und weist vielleicht auf Fehler beim Aufrufer hin) + OTableWindowMap::const_iterator aIter = GetTabWinMap()->find(rAliasName); + if(aIter != GetTabWinMap()->end()) + return static_cast<OQueryTableWindow*>(aIter->second); + return NULL; +} + +//------------------------------------------------------------------------------ +sal_Bool OQueryTableView::FindTableFromField(const String& rFieldName, OTableFieldDesc& rInfo, sal_uInt16& rCnt) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + sal_Bool bRet = sal_False; + rCnt = 0; + OTableWindowMap::const_iterator aIter = GetTabWinMap()->begin(); + for(;aIter != GetTabWinMap()->end();++aIter) + { + if(static_cast<OQueryTableWindow*>(aIter->second)->ExistsField(rFieldName, rInfo)) + rCnt++; + } + + return rCnt == 1; +} + +//------------------------------------------------------------------------------ +sal_Bool OQueryTableView::RemoveTabWin(const String& strAliasName) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + OQueryTableWindow* pTabWin = FindTable(strAliasName); + if (!pTabWin) + return sal_False; + + RemoveTabWin(pTabWin); + return sal_True; +} + +//------------------------------------------------------------------------------ +void OQueryTableView::RemoveTabWin(OTableWindow* pTabWin) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + DBG_ASSERT(pTabWin != NULL, "OQueryTableView::RemoveTabWin : Fenster sollte ungleich NULL sein !"); + DBG_ASSERT(pTabWin->ISA(OQueryTableWindow), "OQueryTableView::RemoveTabWin : Fenster sollte ein OQueryTableWindow sein !"); + + // mein Parent brauche ich, da es vom Loeschen erfahren soll + OQueryDesignView* pParent = getDesignView(); + + SfxUndoManager* pUndoMgr = m_pView->getController()->getUndoMgr(); + pUndoMgr->EnterListAction( String( ModuleRes(STR_QUERY_UNDO_TABWINDELETE) ), String() ); + + // Undo Actions und Loeschen der Felder in SelectionBrowseBox + pParent->TableDeleted( static_cast< OQueryTableWindowData*>(pTabWin->GetData())->GetAliasName() ); + m_pView->getController()->setModified(sal_True); + + // Undo-Action anlegen + OQueryTabWinDelUndoAct* pUndoAction = new OQueryTabWinDelUndoAct(this); + pUndoAction->SetTabWin(static_cast< OQueryTableWindow*>(pTabWin)); + + // und Fenster verstecken + HideTabWin(static_cast< OQueryTableWindow*>(pTabWin), pUndoAction); + + pUndoMgr->AddUndoAction( pUndoAction ); + pUndoMgr->LeaveListAction(); + + m_pView->getController()->InvalidateFeature(ID_BROWSER_UNDORECORD); + m_pView->getController()->InvalidateFeature(ID_BROWSER_REDO); + // GetViewShell()->GetViewShell()->UIFeatureChanged(); + + if (m_lnkTabWinsChangeHandler.IsSet()) + { + TabWinsChangeNotification aHint(TabWinsChangeNotification::AT_REMOVED_WIN, static_cast< OQueryTableWindow*>(pTabWin)->GetAliasName()); + m_lnkTabWinsChangeHandler.Call(&aHint); + } +} + +//------------------------------------------------------------------------------ +void OQueryTableView::HideTabWins() +{ + DBG_CHKTHIS(OQueryTableView,NULL); + SetUpdateMode(sal_False); + + OTableWindowMap* pTabWins = GetTabWinMap(); + if (pTabWins) + { + OTableWindowMap::const_iterator aIter = GetTabWinMap()->begin(); + for(;aIter != GetTabWinMap()->end();++aIter) + RemoveTabWin(aIter->second); + } + + m_pView->getController()->setModified(sal_True); + + SetUpdateMode(sal_True); + +} + +//------------------------------------------------------------------------ +void OQueryTableView::EnsureVisible(const OTableWindow* pWin) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + OJoinTableView::EnsureVisible(pWin); + Invalidate(INVALIDATE_NOCHILDREN); + return; +} + +//------------------------------------------------------------------------ +void OQueryTableView::GetConnection(OQueryTableConnection* pConn) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + // bei mir und dem Dokument einfuegen + GetTabConnList()->push_back(pConn); + m_pView->getController()->getTableConnectionData()->push_back(pConn->GetData()); + + // invalidieren (damit es neu gezeichnet wird) + pConn->Invalidate(); + + // modified-Flag + m_pView->getController()->setModified(sal_True); +} + +//------------------------------------------------------------------------ +void OQueryTableView::DropConnection(OQueryTableConnection* pConn) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + // Selektion beachten + DeselectConn(GetSelectedConn()); + + // bei mir und dem Dokument rausnehmen + GetTabConnList()->erase( ::std::find(GetTabConnList()->begin(),GetTabConnList()->end(),static_cast<OTableConnection*>(pConn))); + m_pView->getController()->getTableConnectionData()->erase( ::std::find(m_pView->getController()->getTableConnectionData()->begin(),m_pView->getController()->getTableConnectionData()->end(),pConn->GetData())); + + // invalidieren (damit es neu gezeichnet wird) + pConn->Invalidate(); + + // modified-Flag + m_pView->getController()->setModified(sal_True); +} + +//------------------------------------------------------------------------ +void OQueryTableView::HideTabWin( OQueryTableWindow* pTabWin, OQueryTabWinUndoAct* pUndoAction ) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + OTableWindowMap* pTabWins = GetTabWinMap(); + DBG_ASSERT(pTabWins != NULL, "OQueryTableView::HideTabWin : habe keine TabWins !"); + + if (pTabWin) + { + // Fenster + // die Position in seinen Daten speichern + getDesignView()->SaveTabWinUIConfig(pTabWin); + // (ich muss ueber das Parent gehen, da nur das die Position der Scrollbars kennt) + // dann aus der Liste der TabWins raus und verstecken + OTableWindowMap::iterator aIter = pTabWins->begin(); + for(;aIter != GetTabWinMap()->end();++aIter) + if(aIter->second == pTabWin) + pTabWins->erase(aIter); + + pTabWin->Hide(); // nicht zerstoeren, steht im Undo!! + + // die Daten zum TabWin muessen auch aus meiner Verantwortung entlassen werden + ::std::vector< OTableWindowData*>* pTabWinDataList = m_pView->getController()->getTableWindowData(); + pTabWinDataList->erase( ::std::find(pTabWinDataList->begin(),pTabWinDataList->end(),pTabWin->GetData())); + // NICHT loeschen, da ja das TabWin selber - das noch lebt - sie auch noch braucht + // Entweder geht es irgendwann wieder in meine Verantwortung ueber, (ueber ShowTabWin), dann fuege ich + // auch die Daten wieder ein, oder die Undo-Action, die im Augenblick die alleinige Verantwortung fuer das Fenster + // und dessen Daten hat, wird zestoert, dann loescht es beides + + if (m_pLastFocusTabWin == pTabWin) + m_pLastFocusTabWin = NULL; + + // Verbindungen, die zum Fenster gehoeren, einsammeln und der UndoAction uebergeben + ::std::vector< OTableConnectionData*>* pTabConnDataList = m_pView->getController()->getTableConnectionData(); + + sal_Int16 nCnt = 0; + ::std::vector<OTableConnection*>* pTabConList = GetTabConnList(); + ::std::vector<OTableConnection*>::iterator aIter2 = pTabConList->begin(); + for(;aIter2 != pTabConList->end();) + { + OQueryTableConnection* pTmpEntry = static_cast<OQueryTableConnection*>(*aIter2); + OSL_ENSURE(pTmpEntry,"OQueryTableConnection is null!"); + if( pTmpEntry->GetAliasName(JTCS_FROM) == pTabWin->GetAliasName() || + pTmpEntry->GetAliasName(JTCS_TO) == pTabWin->GetAliasName() ) + { + pUndoAction->InsertConnection(pTmpEntry); + // die Connection invalidieren (ich kann nicht unten einfach ein InvalidateConnections machen, da ja dann die Connection + // in meiner Liste nicht mehr existiert !) + pTmpEntry->Invalidate(); + + // die Daten aus dem Doc entfernen (Kommentar wie oben bei den Tabellendaten) + pTabConnDataList->erase( ::std::find(pTabConnDataList->begin(),pTabConnDataList->end(),pTmpEntry->GetData()) ); + // die Connection selber weg und weiter + aIter2 = pTabConList->erase(aIter2); // TODO check if this is ok + nCnt++; + } + else + ++aIter2; + } + + if (nCnt) + InvalidateConnections(); + + m_pView->getController()->InvalidateFeature(ID_BROWSER_ADDTABLE); + + // der UndoAction sagen, dass das Fenster (inklusive der Connections) jetzt in seinem Besitzt ist + pUndoAction->SetOwnership(sal_True); + + // damit habe ich das Doc natuerlich modifiziert + m_pView->getController()->setModified( sal_True ); + m_pView->getController()->InvalidateFeature( ID_BROWSER_SAVEDOC ); + m_pView->getController()->InvalidateFeature(ID_BROWSER_CLEAR_QUERY); + } +} + +//------------------------------------------------------------------------ +sal_Bool OQueryTableView::ShowTabWin( OQueryTableWindow* pTabWin, OQueryTabWinUndoAct* pUndoAction ) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + + sal_Bool bSuccess = sal_False; + + if (pTabWin) + { + if (pTabWin->Init()) + { + OTableWindowData* pData = pTabWin->GetData(); + DBG_ASSERT(pData != NULL, "OQueryTableView::ShowTabWin : TabWin hat keine Daten !"); + // Wenn die Daten schon PosSize haben, diese benutzen + if (pData->HasPosition() && pData->HasSize()) + { + Size aSize(CalcZoom(pData->GetSize().Width()),CalcZoom(pData->GetSize().Height())); + pTabWin->SetPosSizePixel(pData->GetPosition(), aSize); + } + else + // ansonsten selber eine Default-Position ermitteln + SetDefaultTabWinPosSize(pTabWin); + + // Fenster zeigen und in Liste eintragen + (*GetTabWinMap())[static_cast< OQueryTableWindowData*>(pData)->GetAliasName()] = pTabWin; + pTabWin->Show(); + + pTabWin->Update(); + // Das Update ist notwendig, damit die Connections an dem Fenster richtig gezeichnet werden. Klingt absurd, + // ich weiss. Aber die Listbox haelt sich intern ein Member, was bei ersten Zeichnen (nachdem die Listbox im Init + // gerade neu gefuellt wurde) initialisiert wird, und genau dieses Member wird irgendwann benoetigt fuer + // GetEntryPos, und dieses wiederum von der Connection, wenn sie ihren Ansatzpunkt am Fenster feststellen will. + + // die Connections + sal_Int16 nCount(0); + ::std::vector<OTableConnection*>* pTableCon = pUndoAction->GetTabConnList(); + ::std::vector<OTableConnection*>::iterator aIter = pTableCon->begin(); + + for(;aIter != pTableCon->end();++aIter,++nCount) + { + // und in meine Liste rein + GetTabConnList()->push_back(*aIter); + // die Daten wieder in das Doc einfuegen + m_pView->getController()->getTableConnectionData()->push_back((*aIter)->GetData()); + } + pTableCon->clear(); + + if (nCount) + InvalidateConnections(); + + // und die Daten des Fensters ebenfalls in Liste (des Docs) + m_pView->getController()->getTableWindowData()->push_back(pTabWin->GetData()); + + m_pView->getController()->InvalidateFeature(ID_BROWSER_ADDTABLE); + + // und der UndoAction sagen, dass das Fenster jetzt meine ist ... + pUndoAction->SetOwnership(sal_False); + + bSuccess = sal_True; + } + else + ////////////////////////////////////////////////////////////////// + // Initialisierung fehlgeschlagen + // (z.B. wenn Verbindung zur Datenbank in diesem Augenblick unterbrochen worden ist) + delete pTabWin; + } + + // damit habe ich das Doc natuerlich modifiziert + if(!m_pView->getController()->isReadOnly()) + m_pView->getController()->setModified( sal_True ); + m_pView->getController()->InvalidateFeature( ID_BROWSER_SAVEDOC ); + m_pView->getController()->InvalidateFeature(ID_BROWSER_CLEAR_QUERY); + + return bSuccess; +} + + +//------------------------------------------------------------------------ +void OQueryTableView::InsertField(const OTableFieldDesc& rInfo) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + DBG_ASSERT(getDesignView() != NULL, "OQueryTableView::InsertField : habe kein Parent !"); + getDesignView()->InsertField(rInfo); +} + +//------------------------------------------------------------------------------ +sal_Bool OQueryTableView::Drop(const DropEvent& rEvt) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + sal_Bool bDrop = sal_False; +/* + SbaDatabaseRef xDatabase(GetDatabase()); + ::com::sun::star::uno::Reference< ::com::sun::star::data::XDatabaseDescriptor > rMetaData = xDatabase->GetMetaData(); + ::com::sun::star::uno::Any aJoin = rMetaData->getInfo(::com::sun::star::data::DatabaseInfo::OUTER_JOIN_SUPPORT); + + if (!xDatabase.Is() || !((::utl::getINT16(aJoin) & ::com::sun::star::data::DatabaseOuterJoinSupport::PARTIAL) || (::utl::getINT16(aJoin) & ::com::sun::star::data::DatabaseOuterJoinSupport::YES)) && GetTabWinMap()->size()) + { + Sound::Beep(); + return sal_False; + } + + sal_Bool bDrop = sal_False; + + for (sal_uInt16 i = 0; i < DragServer::GetItemCount(); ++i) + { + if (INetBookmark::DragServerHasFormat(i) ) + { + INetBookmark aBmk; + if (aBmk.PasteDragServer(i)) + { + INetURLObject aObj(aBmk.GetURL()); + aObj.SetSmartProtocol(INET_PROT_FILE); + String aMark(aObj.GetMark()); + + if (aMark.GetTokenCount(';') > 1) + { + String sType = aMark.GetToken(0, ';'); + sType += ';'; + if (sType == String::CreateFromAscii(SDB_TABLEMARK_HEADER)) + { + aMark.Erase(0, strlen(SDB_TABLEMARK_HEADER)); + + String aDatabaseName = aObj.PathToFileName(); + DirEntry aDBEntry(aDatabaseName); + + if (aDBEntry == DirEntry(xDatabase->Name())) + { + SbaDBDefRef aDef = xDatabase->OpenDBDef(dbTable, aMark); + if (aDef.Is()) + { + if (aDef->Status().IsError()) + SBA_MOD()->ShowDbStatus(aDef->Status(), dbReadError,NULL); + + SdbTable* pTable = (static_cast< SbaTableDef*>(&aDef)->GetTable(); + if (pTable && pTable->IsOpen()) + { + AddTabWin(pTable->QualifierName(),pTable->GetFullName()); + bDrop = sal_True; + } + } + } + } + } + + if (!bDrop) + Sound::Beep(); + break; + } + } + } +*/ + return bDrop; +} + +//------------------------------------------------------------------------------ +sal_Bool OQueryTableView::QueryDrop(DropEvent& rEvt) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + sal_Bool bDrop = sal_False; +/* + SbaDatabaseRef xDatabase(GetDatabase()); + + ::com::sun::star::uno::Reference< ::com::sun::star::data::XDatabaseDescriptor > rMetaData = xDatabase->GetMetaData(); + ::com::sun::star::uno::Any aJoin = rMetaData->getInfo(::com::sun::star::data::DatabaseInfo::OUTER_JOIN_SUPPORT); + if (!xDatabase.Is() || !((::utl::getINT16(aJoin) & ::com::sun::star::data::DatabaseOuterJoinSupport::PARTIAL) || (::utl::getINT16(aJoin) & ::com::sun::star::data::DatabaseOuterJoinSupport::YES)) && GetTabWinMap()->size()) + return sal_False; + + sal_Bool bDrop = sal_False; + DropAction eAction = rEvt.GetAction(); + + for (sal_uInt16 i = 0; i < DragServer::GetItemCount(); ++i) + { + if (INetBookmark::DragServerHasFormat(i)) + { + INetBookmark aBmk; + if (aBmk.PasteDragServer(i)) + { // it's a INetBookmark + INetURLObject aObj(aBmk.GetURL()); + aObj.SetSmartProtocol(INET_PROT_FILE); + String aMark(aObj.GetMark()); + + // maybe it's a reference to a db object + if (aMark.GetTokenCount(';') > 1) + { + String sType = aMark.GetToken(0, ';'); + sType += ';'; + if (sType == String::CreateFromAscii(SDB_TABLEMARK_HEADER)) + { // it's a reference to a table + aMark.Erase(0, strlen(SDB_TABLEMARK_HEADER)); + + String aDatabaseName = aObj.PathToFileName(); + DirEntry aDBEntry(aDatabaseName); + + if (aDBEntry == DirEntry(xDatabase->Name())) + { // it's a reference to a table of our own database + if (xDatabase->HasObjectByURL(aObj.GetMainURL())) + { + rEvt.SetAction(DROP_COPY); + bDrop = sal_True; + break; + } + } + } + } + } + } + } +*/ + return bDrop; +} +//------------------------------------------------------------------------------ +sal_Bool OQueryTableView::ExistsAVisitedConn(const OQueryTableWindow* pFrom) const +{ + DBG_CHKTHIS(OQueryTableView,NULL); + ::std::vector<OTableConnection*>* pList = const_cast< OQueryTableView*>(this)->GetTabConnList(); + if (pList) + { + ::std::vector<OTableConnection*>::iterator aIter = pList->begin(); + for(;aIter != pList->end();++aIter) + { + OQueryTableConnection* pTemp = static_cast<OQueryTableConnection*>(*aIter); + if (pTemp->IsVisited() && + (pFrom == static_cast< OQueryTableWindow*>(pTemp->GetSourceWin()) || pFrom == static_cast< OQueryTableWindow*>(pTemp->GetDestWin()))) + return pTemp != NULL; + } + } + + return sal_False; +} +// ----------------------------------------------------------------------------- + + + + |