/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org 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 version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_dbaccess.hxx" #include "RelationTableView.hxx" #include "JoinExchange.hxx" #include #include "browserids.hxx" #include #include #include #include #include #include #include #include #include "dbustrings.hrc" #include #include #include #include "dbaccess_helpid.hrc" #include "RelationDesignView.hxx" #include "JoinController.hxx" #include "TableWindow.hxx" #include "TableWindowData.hxx" #include "RTableConnection.hxx" #include "RTableConnectionData.hxx" #include "RelationDlg.hxx" #include "sqlmessage.hxx" #include "dbu_rel.hrc" #include "UITools.hxx" #include #include "RTableWindow.hxx" #include "JAccess.hxx" #include #include using namespace dbaui; using namespace ::dbtools; using namespace ::com::sun::star; 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; using namespace ::com::sun::star::accessibility; //================================================================== // class ORelationTableView //================================================================== DBG_NAME(ORelationTableView) //------------------------------------------------------------------------ ORelationTableView::ORelationTableView( Window* pParent, ORelationDesignView* pView ) :OJoinTableView( pParent, pView ) , ::comphelper::OContainerListener(m_aMutex) ,m_pExistingConnection(NULL) ,m_bInRemove(false) { DBG_CTOR(ORelationTableView,NULL); SetHelpId(HID_CTL_RELATIONTAB); } //------------------------------------------------------------------------ ORelationTableView::~ORelationTableView() { DBG_DTOR(ORelationTableView,NULL); if ( m_pContainerListener.is() ) m_pContainerListener->dispose(); } //------------------------------------------------------------------------ void ORelationTableView::ReSync() { DBG_CHKTHIS(ORelationTableView,NULL); if ( !m_pContainerListener.is() ) { Reference< XConnection> xConnection = m_pView->getController().getConnection(); Reference< XTablesSupplier > xTableSupp( xConnection, UNO_QUERY_THROW ); Reference< XNameAccess > xTables = xTableSupp->getTables(); Reference< XContainer> xContainer(xTables,uno::UNO_QUERY); if ( xContainer.is() ) m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer); } // Es kann sein, dass in der DB Tabellen ausgeblendet wurden, die eigentlich Bestandteil einer Relation sind. Oder eine Tabelle // befand sich im Layout (durchaus ohne Relation), existiert aber nicht mehr. In beiden Faellen wird das Anlegen des TabWins schief // gehen, und alle solchen TabWinDatas oder darauf bezogenen ConnDatas muss ich dann loeschen. ::std::vector< ::rtl::OUString> arrInvalidTables; ////////////////////////////////////////////////////////////////////// // create and insert windows TTableWindowData* pTabWinDataList = m_pView->getController().getTableWindowData(); TTableWindowData::reverse_iterator aIter = pTabWinDataList->rbegin(); for(;aIter != pTabWinDataList->rend();++aIter) { TTableWindowData::value_type pData = *aIter; OTableWindow* pTabWin = createWindow(pData); 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 pTabWin->clearListBox(); delete pTabWin; arrInvalidTables.push_back(pData->GetTableName()); pTabWinDataList->erase( ::std::remove(pTabWinDataList->begin(),pTabWinDataList->end(),*aIter) ,pTabWinDataList->end()); continue; } (*GetTabWinMap())[pData->GetComposedName()] = 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 TTableConnectionData* pTabConnDataList = m_pView->getController().getTableConnectionData(); TTableConnectionData::reverse_iterator aConIter = pTabConnDataList->rbegin(); for(;aConIter != pTabConnDataList->rend();++aConIter) { ORelationTableConnectionData* pTabConnData = static_cast(aConIter->get()); if ( !arrInvalidTables.empty() ) { // gibt es die beiden Tabellen zur Connection ? ::rtl::OUString strTabExistenceTest = pTabConnData->getReferencingTable()->GetTableName(); sal_Bool bInvalid = ::std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end(); strTabExistenceTest = pTabConnData->getReferencedTable()->GetTableName(); bInvalid = bInvalid || ::std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end(); if (bInvalid) { // nein -> Pech gehabt, die Connection faellt weg pTabConnDataList->erase( ::std::remove(pTabConnDataList->begin(),pTabConnDataList->end(),*aConIter),pTabConnDataList->end() ); continue; } } // if ( !arrInvalidTables.empty() ) addConnection( new ORelationTableConnection(this, *aConIter), sal_False ); // don't add the data again } if ( !GetTabWinMap()->empty() ) GetTabWinMap()->begin()->second->GrabFocus(); } //------------------------------------------------------------------------------ BOOL ORelationTableView::IsAddAllowed() { DBG_CHKTHIS(ORelationTableView,NULL); return !m_pView->getController().isReadOnly(); } //------------------------------------------------------------------------ void ORelationTableView::AddConnection(const OJoinExchangeData& jxdSource, const OJoinExchangeData& jxdDest) { DBG_CHKTHIS(ORelationTableView,NULL); // Aus selektierten Feldnamen LineDataObject setzen // check if relation already exists OTableWindow* pSourceWin = jxdSource.pListBox->GetTabWin(); OTableWindow* pDestWin = jxdDest.pListBox->GetTabWin(); ::std::vector::const_iterator aIter = getTableConnections()->begin(); ::std::vector::const_iterator aEnd = getTableConnections()->end(); for(;aIter != aEnd;++aIter) { OTableConnection* pFirst = *aIter; if((pFirst->GetSourceWin() == pSourceWin && pFirst->GetDestWin() == pDestWin) || (pFirst->GetSourceWin() == pDestWin && pFirst->GetDestWin() == pSourceWin)) { m_pExistingConnection = pFirst; break; } } // insert table connection into view TTableConnectionData::value_type pTabConnData(new ORelationTableConnectionData(pSourceWin->GetData(), pDestWin->GetData())); // die Namen der betroffenen Felder ::rtl::OUString sSourceFieldName = jxdSource.pListBox->GetEntryText(jxdSource.pEntry); ::rtl::OUString sDestFieldName = jxdDest.pListBox->GetEntryText(jxdDest.pEntry); // die Anzahl der PKey-Felder in der Quelle const Reference< XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(pSourceWin->GetData()->getTable()); bool bAskUser = xPrimaryKeyColumns.is() && Reference< XIndexAccess>(xPrimaryKeyColumns,UNO_QUERY)->getCount() > 1; pTabConnData->SetConnLine( 0, sSourceFieldName, sDestFieldName ); if ( bAskUser || m_pExistingConnection ) m_pCurrentlyTabConnData = pTabConnData; // this implies that we ask the user what to do else { try { ////////////////////////////////////////////////////////////////////// // Daten der Datenbank uebergeben if( pTabConnData->Update() ) { ////////////////////////////////////////////////////////////////////// // UI-Object in ConnListe eintragen addConnection( new ORelationTableConnection( this, pTabConnData ) ); } } catch(const SQLException&) { throw; } catch(const Exception&) { OSL_ENSURE(0,"ORelationTableView::AddConnection: Exception oocured!"); } } } //------------------------------------------------------------------------ void ORelationTableView::ConnDoubleClicked( OTableConnection* pConnection ) { DBG_CHKTHIS(ORelationTableView,NULL); ORelationDialog aRelDlg( this, pConnection->GetData() ); switch (aRelDlg.Execute()) { case RET_OK: // successfully updated pConnection->UpdateLineList(); // The connection references 1 ConnData and n ConnLines, each ConnData references n LineDatas, each Line exactly 1 LineData // As the Dialog and the ConnData->Update may have changed the LineDatas we have to restore the consistent state break; case RET_NO: // tried at least one update, but did not succeed -> the original connection is lost RemoveConnection( pConnection ,sal_True); break; case RET_CANCEL: // no break, as nothing happened and we don't need the code below return; } Invalidate(INVALIDATE_NOCHILDREN); } //------------------------------------------------------------------------------ void ORelationTableView::AddNewRelation() { DBG_CHKTHIS(ORelationTableView,NULL); TTableConnectionData::value_type pNewConnData( new ORelationTableConnectionData() ); ORelationDialog aRelDlg(this, pNewConnData, TRUE); BOOL bSuccess = (aRelDlg.Execute() == RET_OK); if (bSuccess) { // already updated by the dialog // dem Dokument bekanntgeben addConnection( new ORelationTableConnection(this, pNewConnData) ); } } //------------------------------------------------------------------------------ bool ORelationTableView::RemoveConnection( OTableConnection* pConn ,sal_Bool /*_bDelete*/) { DBG_CHKTHIS(ORelationTableView,NULL); ORelationTableConnectionData* pTabConnData = (ORelationTableConnectionData*)pConn->GetData().get(); try { if ( m_bInRemove || pTabConnData->DropRelation()) return OJoinTableView::RemoveConnection( pConn ,sal_True); } catch(SQLException& e) { getDesignView()->getController().showError(SQLExceptionInfo(e)); } catch(Exception&) { OSL_ENSURE(0,"ORelationTableView::RemoveConnection: Something other than SQLException occured!"); } return false; } //------------------------------------------------------------------------------ void ORelationTableView::AddTabWin(const ::rtl::OUString& _rComposedName, const ::rtl::OUString& rWinName, BOOL /*bNewTable*/) { DBG_CHKTHIS(ORelationTableView,NULL); OSL_ENSURE(_rComposedName.getLength(),"There must be a table name supplied!"); OJoinTableView::OTableWindowMap::iterator aIter = GetTabWinMap()->find(_rComposedName); if(aIter != GetTabWinMap()->end()) { aIter->second->SetZOrder(NULL, WINDOW_ZORDER_FIRST); aIter->second->GrabFocus(); EnsureVisible(aIter->second); // no new one return; } ////////////////////////////////////////////////////////////////// // Neue Datenstruktur in DocShell eintragen TTableWindowData::value_type pNewTabWinData(createTableWindowData( _rComposedName, rWinName,rWinName )); pNewTabWinData->ShowAll(FALSE); ////////////////////////////////////////////////////////////////// // Neues Fenster in Fensterliste eintragen OTableWindow* pNewTabWin = createWindow( pNewTabWinData ); if(pNewTabWin->Init()) { m_pView->getController().getTableWindowData()->push_back( pNewTabWinData); // when we already have a table with this name insert the full qualified one instead (*GetTabWinMap())[_rComposedName] = pNewTabWin; SetDefaultTabWinPosSize( pNewTabWin ); pNewTabWin->Show(); modified(); if ( m_pAccessible ) m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD, Any(), makeAny(pNewTabWin->GetAccessible())); } else { pNewTabWin->clearListBox(); delete pNewTabWin; } } // ----------------------------------------------------------------------------- void ORelationTableView::RemoveTabWin( OTableWindow* pTabWin ) { OSQLWarningBox aDlg( this, ModuleRes( STR_QUERY_REL_DELETE_WINDOW ), WB_YES_NO | WB_DEF_YES ); if ( m_bInRemove || aDlg.Execute() == RET_YES ) { m_pView->getController().getUndoMgr()->Clear(); OJoinTableView::RemoveTabWin( pTabWin ); m_pView->getController().InvalidateFeature(SID_RELATION_ADD_RELATION); m_pView->getController().InvalidateFeature(ID_BROWSER_UNDO); m_pView->getController().InvalidateFeature(ID_BROWSER_REDO); } } // ----------------------------------------------------------------------------- //namespace //{ // class OReleationAskDialog : public ButtonDialog // { // FixedImage m_aInfoImage; // FixedText m_aTitle; // FixedText m_aMessage; // public: // OReleationDialog(Window* _pParent) : ButtonDialog(_pParent,WB_HORZ | WB_STDDIALOG) // ,m_aInfoImage(this) // ,m_aTitle(this,WB_WORDBREAK | WB_LEFT) // ,m_aMessage(this,WB_WORDBREAK | WB_LEFT) // { // m_aMessage.SetText(ModuleRes(STR_QUERY_REL_EDIT_RELATION)); // m_aMessage.Show(); // // // Changed as per BugID 79541 Branding/Configuration // String sDialogTitle( lcl_getProductName() ); // SetText( sDialogTitle.AppendAscii( " Base" ) ); // m_aTitle.Show(); // } // }; //} // ----------------------------------------------------------------------------- void ORelationTableView::lookForUiActivities() { if(m_pExistingConnection) { String sTitle(ModuleRes(STR_RELATIONDESIGN)); sTitle.Erase(0,3); OSQLMessageBox aDlg(this,ModuleRes(STR_QUERY_REL_EDIT_RELATION),String(),0); aDlg.SetText(sTitle); aDlg.RemoveButton(aDlg.GetButtonId(0)); aDlg.AddButton( ModuleRes(STR_QUERY_REL_EDIT), BUTTONID_OK, BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON); aDlg.AddButton( ModuleRes(STR_QUERY_REL_CREATE), BUTTONID_YES, 0); aDlg.AddButton(BUTTON_CANCEL,BUTTONID_CANCEL,0); UINT16 nRet = aDlg.Execute(); if( nRet == RET_CANCEL) { m_pCurrentlyTabConnData.reset(); } else if ( nRet == RET_OK ) // EDIT { ConnDoubleClicked(m_pExistingConnection); m_pCurrentlyTabConnData.reset(); } m_pExistingConnection = NULL; } if(m_pCurrentlyTabConnData) { ORelationDialog aRelDlg( this, m_pCurrentlyTabConnData ); if (aRelDlg.Execute() == RET_OK) { // already updated by the dialog addConnection( new ORelationTableConnection( this, m_pCurrentlyTabConnData ) ); } m_pCurrentlyTabConnData.reset(); } } // ----------------------------------------------------------------------------- OTableWindow* ORelationTableView::createWindow(const TTableWindowData::value_type& _pData) { return new ORelationTableWindow(this,_pData); } // ----------------------------------------------------------------------------- bool ORelationTableView::allowQueries() const { return false; } // ----------------------------------------------------------------------------- void ORelationTableView::_elementInserted( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException) { } // ----------------------------------------------------------------------------- void ORelationTableView::_elementRemoved( const container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException) { m_bInRemove = true; ::rtl::OUString sName; if ( _rEvent.Accessor >>= sName ) { OTableWindow* pTableWindow = GetTabWindow(sName); if ( pTableWindow ) { m_pView->getController().getUndoMgr()->Clear(); OJoinTableView::RemoveTabWin( pTableWindow ); m_pView->getController().InvalidateFeature(SID_RELATION_ADD_RELATION); m_pView->getController().InvalidateFeature(ID_BROWSER_UNDO); m_pView->getController().InvalidateFeature(ID_BROWSER_REDO); } } // if ( _rEvent.Accessor >>= sName ) m_bInRemove = false; } // ----------------------------------------------------------------------------- void ORelationTableView::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException) { } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */