diff options
Diffstat (limited to 'dbaccess/source/ui/querydesign')
54 files changed, 19276 insertions, 0 deletions
diff --git a/dbaccess/source/ui/querydesign/ConnectionLine.cxx b/dbaccess/source/ui/querydesign/ConnectionLine.cxx new file mode 100644 index 000000000000..4c119ca15c78 --- /dev/null +++ b/dbaccess/source/ui/querydesign/ConnectionLine.cxx @@ -0,0 +1,385 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "ConnectionLine.hxx" +#include "ConnectionLineData.hxx" +#include "TableWindow.hxx" +#include "TableWindowListBox.hxx" +#include "TableConnection.hxx" +#include <vcl/svapp.hxx> +#ifndef _INC_MATH +#include <math.h> +#endif +#include <tools/debug.hxx> +#include <vcl/lineinfo.hxx> + + +using namespace dbaui; +const long DESCRIPT_LINE_WIDTH = 15; +const long HIT_SENSITIVE_RADIUS = 5; + +namespace +{ + /** calcRect creates a new rectangle with the given points + @param _rBase the base point + @param _aVector the vector which will be added + */ + inline Rectangle calcRect(const Point& _rBase,const Point& _aVector) + { + return Rectangle( _rBase - _aVector, _rBase + _aVector ); + } + // ----------------------------------------------------------------------------- + /** GetTextPos calculate the rectangle for the connection to be drawn + @param _pWin the table window where to draw it + @param _aConnPos the connection point + @param _aDescrLinePos the description line pos + */ + Rectangle GetTextPos(const OTableWindow* _pWin, const Point& _aConnPos,const Point& _aDescrLinePos) + { + OTableWindowListBox* pListBox = _pWin ? _pWin->GetListBox() : NULL; + DBG_ASSERT(_pWin && pListBox, "OConnectionLine::GetSourceTextPos : invalid call !"); + + Rectangle aReturn; + if ( pListBox ) + { + const long nRowHeight = pListBox->GetEntryHeight(); + aReturn.Top() = _aConnPos.Y() - nRowHeight; + aReturn.Bottom() = aReturn.Top() + nRowHeight; + if (_aDescrLinePos.X() < _aConnPos.X()) + { + aReturn.Left() = _aDescrLinePos.X(); + aReturn.Right() = aReturn.Left() + _aConnPos.X() - _aDescrLinePos.X(); + } + else + { + aReturn.Left() = _aConnPos.X(); + aReturn.Right() = aReturn.Left() + _aDescrLinePos.X() - _aConnPos.X(); + } + } + + return aReturn; + } + // ----------------------------------------------------------------------------- + /** calcPointsYValue calculate the points Y value in relation to the listbox entry + @param _pWin the corresponding window + @param _pEntry the source or dest entry + @param _rNewConPos (in/out) the connection pos + @param _rNewDescrPos (in/out) the description pos + */ + void calcPointsYValue(const OTableWindow* _pWin,SvLBoxEntry* _pEntry,Point& _rNewConPos,Point& _rNewDescrPos) + { + const OTableWindowListBox* pListBox = _pWin->GetListBox(); + _rNewConPos.Y() = _pWin->GetPosPixel().Y(); + if ( _pEntry ) + { + const long nRowHeight = pListBox->GetEntryHeight(); + _rNewConPos.Y() += pListBox->GetPosPixel().Y(); + long nEntryPos = pListBox->GetEntryPosition( _pEntry ).Y(); + + if( nEntryPos >= 0 ) + { + _rNewConPos.Y() += nEntryPos; + _rNewConPos.Y() += (long)( 0.5 * nRowHeight ); + } + else + _rNewConPos.Y() -= (long)( 0.5 * nRowHeight ); + + long nListBoxBottom = _pWin->GetPosPixel().Y() + + pListBox->GetPosPixel().Y() + + pListBox->GetSizePixel().Height(); + if( _rNewConPos.Y() > nListBoxBottom ) + _rNewConPos.Y() = nListBoxBottom + 2; + } + else + _rNewConPos.Y() += static_cast<sal_Int32>(pListBox->GetPosPixel().Y()*0.5); + + _rNewDescrPos.Y() = _rNewConPos.Y(); + } + // ----------------------------------------------------------------------------- +} + +//======================================================================== +// class OConnectionLine +//======================================================================== +DBG_NAME(OConnectionLine) +//------------------------------------------------------------------------ +OConnectionLine::OConnectionLine( OTableConnection* _pConn, OConnectionLineDataRef _pLineData ) + : m_pTabConn( _pConn ) + ,m_pData( _pLineData ) +{ + DBG_CTOR(OConnectionLine,NULL); +} + +//------------------------------------------------------------------------ +OConnectionLine::OConnectionLine( const OConnectionLine& _rLine ) +{ + DBG_CTOR(OConnectionLine,NULL); + m_pData = new OConnectionLineData( *_rLine.GetData() ); + *this = _rLine; +} + +//------------------------------------------------------------------------ +OConnectionLine::~OConnectionLine() +{ + DBG_DTOR(OConnectionLine,NULL); +} + +//------------------------------------------------------------------------ +OConnectionLine& OConnectionLine::operator=( const OConnectionLine& rLine ) +{ + if( &rLine != this ) + { + // da mir die Daten nicht gehoeren, loesche ich die alten nicht + m_pData->CopyFrom(*rLine.GetData()); + // CopyFrom ist virtuell, damit ist es kein Problem, wenn m_pData von einem von OTableConnectionData abgeleiteten Typ ist + + m_pTabConn = rLine.m_pTabConn; + m_aSourceConnPos = rLine.m_aSourceConnPos; + m_aDestConnPos = rLine.m_aDestConnPos; + m_aSourceDescrLinePos = rLine.m_aSourceDescrLinePos; + m_aDestDescrLinePos = rLine.m_aDestDescrLinePos; + } + + return *this; +} + +//------------------------------------------------------------------------ +Rectangle OConnectionLine::GetBoundingRect() +{ + ////////////////////////////////////////////////////////////////////// + // Umgebendes Rechteck bestimmen + Rectangle aBoundingRect( Point(0,0), Point(0,0) ); + if( !IsValid() ) + return aBoundingRect; + + Point aTopLeft; + Point aBottomRight; + + if( m_aSourceDescrLinePos.Y() <= m_aDestDescrLinePos.Y() ) + { + aTopLeft.Y() = m_aSourceDescrLinePos.Y(); + aBottomRight.Y() = m_aDestDescrLinePos.Y(); + } + else + { + aTopLeft.Y() = m_aDestDescrLinePos.Y(); + aBottomRight.Y() = m_aSourceDescrLinePos.Y(); + } + + if( m_aSourceDescrLinePos.X() <= m_aDestDescrLinePos.X() ) + { + aTopLeft.X() = m_aSourceDescrLinePos.X(); + aBottomRight.X() = m_aDestDescrLinePos.X(); + } + else + { + aTopLeft.X() = m_aDestDescrLinePos.X(); + aBottomRight.X() = m_aSourceDescrLinePos.X(); + } + + const OTableWindow* pSourceWin = m_pTabConn->GetSourceWin(); + const OTableWindow* pDestWin = m_pTabConn->GetDestWin(); + ////////////////////////////////////////////////////////////////////// + // Linie verlaeuft in z-Form + if( pSourceWin == pDestWin || Abs(m_aSourceConnPos.X() - m_aDestConnPos.X()) > Abs(m_aSourceDescrLinePos.X() - m_aDestDescrLinePos.X()) ) + { + aTopLeft.X() -= DESCRIPT_LINE_WIDTH; + aBottomRight.X() += DESCRIPT_LINE_WIDTH; + } + + aBoundingRect = Rectangle( aTopLeft-Point(2,17), aBottomRight+Point(2,2) ); + + return aBoundingRect; +} +// ----------------------------------------------------------------------------- +void calcPointX1(const OTableWindow* _pWin,Point& _rNewConPos,Point& _rNewDescrPos) +{ + _rNewConPos.X() = _pWin->GetPosPixel().X() + _pWin->GetSizePixel().Width(); + _rNewDescrPos.X() = _rNewConPos.X(); + _rNewConPos.X() += DESCRIPT_LINE_WIDTH; +} +// ----------------------------------------------------------------------------- +void calcPointX2(const OTableWindow* _pWin,Point& _rNewConPos,Point& _rNewDescrPos) +{ + _rNewConPos.X() = _pWin->GetPosPixel().X(); + _rNewDescrPos.X() = _rNewConPos.X(); + _rNewConPos.X() -= DESCRIPT_LINE_WIDTH; +} +//------------------------------------------------------------------------ +BOOL OConnectionLine::RecalcLine() +{ + ////////////////////////////////////////////////////////////////////// + // Fenster und Entries muessen gesetzt sein + const OTableWindow* pSourceWin = m_pTabConn->GetSourceWin(); + const OTableWindow* pDestWin = m_pTabConn->GetDestWin(); + + if( !pSourceWin || !pDestWin ) + return FALSE; + + SvLBoxEntry* pSourceEntry = pSourceWin->GetListBox()->GetEntryFromText( GetData()->GetSourceFieldName() ); + SvLBoxEntry* pDestEntry = pDestWin->GetListBox()->GetEntryFromText( GetData()->GetDestFieldName() ); + + ////////////////////////////////////////////////////////////////////// + // X-Koordinaten bestimmen + Point aSourceCenter( 0, 0 ); + Point aDestCenter( 0, 0 ); + + aSourceCenter.X() = pSourceWin->GetPosPixel().X() + (long)( 0.5*pSourceWin->GetSizePixel().Width() ); + aDestCenter.X() = pDestWin->GetPosPixel().X() + (long)( 0.5*pDestWin->GetSizePixel().Width() ); + + const OTableWindow* pFirstWin = pDestWin; + const OTableWindow* pSecondWin = pSourceWin; + Point* pFirstConPos = &m_aDestConnPos; + Point* pFirstDescrPos = &m_aDestDescrLinePos; + Point* pSecondConPos = &m_aSourceConnPos; + Point* pSecondDescrPos = &m_aSourceDescrLinePos; + if( aDestCenter.X() > aSourceCenter.X() ) + { + pFirstWin = pSourceWin; + pSecondWin = pDestWin; + pFirstConPos = &m_aSourceConnPos; + pFirstDescrPos = &m_aSourceDescrLinePos; + pSecondConPos = &m_aDestConnPos; + pSecondDescrPos = &m_aDestDescrLinePos; + } + + if ( pFirstWin == pSecondWin && pSourceEntry != pDestEntry ) + calcPointX2(pFirstWin,*pFirstConPos,*pFirstDescrPos); + else + calcPointX1(pFirstWin,*pFirstConPos,*pFirstDescrPos); + calcPointX2(pSecondWin,*pSecondConPos,*pSecondDescrPos); + + ////////////////////////////////////////////////////////////////////// + // aSourceConnPosY bestimmen + calcPointsYValue(pSourceWin,pSourceEntry,m_aSourceConnPos,m_aSourceDescrLinePos); + + ////////////////////////////////////////////////////////////////////// + // aDestConnPosY bestimmen + calcPointsYValue(pDestWin,pDestEntry,m_aDestConnPos,m_aDestDescrLinePos); + + return TRUE; +} +// ----------------------------------------------------------------------------- + +//------------------------------------------------------------------------ +void OConnectionLine::Draw( OutputDevice* pOutDev ) +{ + const UINT16 nRectSize = 3; + + ////////////////////////////////////////////////////////////////////// + // Neue Dimensionen berechnen + if( !RecalcLine() ) + return; + + ////////////////////////////////////////////////////////////////////// + // Zeichnen der Linien + if (m_pTabConn->IsSelected()) + pOutDev->SetLineColor(Application::GetSettings().GetStyleSettings().GetHighlightColor()); + else + pOutDev->SetLineColor(Application::GetSettings().GetStyleSettings().GetWindowTextColor()); + + LineInfo aLineInfo; + if ( m_pTabConn->IsSelected() ) + aLineInfo.SetWidth(3); + Polygon aPoly; + aPoly.Insert(0,m_aSourceDescrLinePos); + aPoly.Insert(1,m_aSourceConnPos); + aPoly.Insert(2,m_aDestConnPos); + aPoly.Insert(3,m_aDestDescrLinePos); + pOutDev->DrawPolyLine(aPoly,aLineInfo); + + ////////////////////////////////////////////////////////////////////// + // draw the connection rectangles + pOutDev->SetFillColor(Application::GetSettings().GetStyleSettings().GetWindowColor()); + + Point aVector(nRectSize,nRectSize); + pOutDev->DrawRect( calcRect(m_aSourceDescrLinePos,aVector) ); + pOutDev->DrawRect( calcRect( m_aDestDescrLinePos,aVector) ); +} +// ----------------------------------------------------------------------------- +BOOL OConnectionLine::IsValid() const +{ + return m_pData.is(); +} +//------------------------------------------------------------------------ +double dist_Euklid(const Point &p1, const Point& p2,const Point& pM, Point& q) +{ + Point v(p2 - p1); + Point w(pM - p1); + double a = sqrt((double)(v.X()*v.X() + v.Y()*v.Y())); + double l = (v.X() * w.Y() - v.Y() * w.X()) / a; + double a2 = w.X()*v.X()+w.Y()*v.Y(); + a = a2 / (a * a); + q.X() = long(p1.X() + a * v.X()); + q.Y() = long(p1.Y() + a * v.Y()); + return l; +} +//------------------------------------------------------------------------ +bool OConnectionLine::CheckHit( const Point& rMousePos ) const +{ + ////////////////////////////////////////////////////////////////////// + /* + Vorgehensweise beim HitTest: + Es wird der Abstand nach Euklid berechnet. + */ + Point q; + double l = fabs(dist_Euklid(m_aSourceConnPos,m_aDestConnPos,rMousePos,q)); + if( l < HIT_SENSITIVE_RADIUS) + { + if(::std::min(m_aSourceConnPos.X(),m_aDestConnPos.X()) <= q.X() && ::std::min(m_aSourceConnPos.Y(),m_aDestConnPos.Y()) <= q.Y() + && q.X() <= ::std::max(m_aDestConnPos.X(),m_aSourceConnPos.X()) && q.Y() <= ::std::max(m_aDestConnPos.Y(),m_aSourceConnPos.Y())) + return true; + } + + return false; +} +// ----------------------------------------------------------------------------- +Rectangle OConnectionLine::GetSourceTextPos() const +{ + return GetTextPos(m_pTabConn->GetSourceWin(),m_aSourceConnPos,m_aSourceDescrLinePos); +} +// ----------------------------------------------------------------------------- +Rectangle OConnectionLine::GetDestTextPos() const +{ + return GetTextPos(m_pTabConn->GetDestWin(),m_aDestConnPos,m_aDestDescrLinePos); +} +// ----------------------------------------------------------------------------- +Point OConnectionLine::getMidPoint() const +{ + Point aDest = m_aDestConnPos - m_aSourceConnPos; + aDest.X() /= 2; + aDest.Y() /= 2; + + return m_aSourceConnPos + aDest; +} +// ----------------------------------------------------------------------------- + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/ConnectionLineAccess.cxx b/dbaccess/source/ui/querydesign/ConnectionLineAccess.cxx new file mode 100644 index 000000000000..a1297dfc68b0 --- /dev/null +++ b/dbaccess/source/ui/querydesign/ConnectionLineAccess.cxx @@ -0,0 +1,251 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "ConnectionLineAccess.hxx" +#include "JoinTableView.hxx" +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleRelationType.hpp> +#include <toolkit/awt/vclxwindow.hxx> +#include "TableConnection.hxx" +#include "TableWindow.hxx" +#include <comphelper/uno3.hxx> +#include "JoinDesignView.hxx" +#include "JoinController.hxx" +#include <comphelper/sequence.hxx> + +namespace dbaui +{ + using namespace ::com::sun::star::accessibility; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star; + + OConnectionLineAccess::OConnectionLineAccess(OTableConnection* _pLine) + : VCLXAccessibleComponent(_pLine->GetComponentInterface().is() ? _pLine->GetWindowPeer() : NULL) + ,m_pLine(_pLine) + { + } + // ----------------------------------------------------------------------------- + void SAL_CALL OConnectionLineAccess::disposing() + { + m_pLine = NULL; + VCLXAccessibleComponent::disposing(); + } + // ----------------------------------------------------------------------------- + Any SAL_CALL OConnectionLineAccess::queryInterface( const Type& aType ) throw (RuntimeException) + { + Any aRet(VCLXAccessibleComponent::queryInterface( aType )); + return aRet.hasValue() ? aRet : OConnectionLineAccess_BASE::queryInterface( aType ); + } + // ----------------------------------------------------------------------------- + Sequence< Type > SAL_CALL OConnectionLineAccess::getTypes( ) throw (RuntimeException) + { + return ::comphelper::concatSequences(VCLXAccessibleComponent::getTypes(),OConnectionLineAccess_BASE::getTypes()); + } + // ----------------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OConnectionLineAccess::getImplementationName() throw(RuntimeException) + { + return getImplementationName_Static(); + } + // ----------------------------------------------------------------------------- + // XServiceInfo - static methods + // ----------------------------------------------------------------------------- + ::rtl::OUString OConnectionLineAccess::getImplementationName_Static(void) throw( RuntimeException ) + { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.dbu.ConnectionLineAccessibility")); + } + // ----------------------------------------------------------------------------- + // XAccessibleContext + sal_Int32 SAL_CALL OConnectionLineAccess::getAccessibleChildCount( ) throw (RuntimeException) + { + return 0; + } + // ----------------------------------------------------------------------------- + Reference< XAccessible > SAL_CALL OConnectionLineAccess::getAccessibleChild( sal_Int32 /*i*/ ) throw (RuntimeException) + { + return Reference< XAccessible >(); + } + // ----------------------------------------------------------------------------- + sal_Int32 SAL_CALL OConnectionLineAccess::getAccessibleIndexInParent( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + sal_Int32 nIndex = -1; + if( m_pLine ) + { + // search the postion of our table window in the table window map + nIndex = m_pLine->GetParent()->GetTabWinMap()->size(); + const ::std::vector<OTableConnection*>* pVec = m_pLine->GetParent()->getTableConnections(); + ::std::vector<OTableConnection*>::const_iterator aIter = pVec->begin(); + ::std::vector<OTableConnection*>::const_iterator aEnd = pVec->end(); + for (; aIter != aEnd && (*aIter) != m_pLine; ++nIndex,++aIter) + ; + nIndex = ( aIter != aEnd ) ? nIndex : -1; + } + return nIndex; + } + // ----------------------------------------------------------------------------- + sal_Int16 SAL_CALL OConnectionLineAccess::getAccessibleRole( ) throw (RuntimeException) + { + return AccessibleRole::UNKNOWN; // ? or may be an AccessibleRole::WINDOW + } + // ----------------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OConnectionLineAccess::getAccessibleDescription( ) throw (RuntimeException) + { + static ::rtl::OUString sDescription(RTL_CONSTASCII_USTRINGPARAM("Relation")); + return sDescription; + } + // ----------------------------------------------------------------------------- + Reference< XAccessibleRelationSet > SAL_CALL OConnectionLineAccess::getAccessibleRelationSet( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return this; + } + // ----------------------------------------------------------------------------- + // XAccessibleComponent + sal_Bool SAL_CALL OConnectionLineAccess::contains( const awt::Point& _aPoint ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + Point aPoint(_aPoint.X,_aPoint.Y); + return m_pLine ? m_pLine->CheckHit(aPoint) : sal_False; + } + // ----------------------------------------------------------------------------- + Reference< XAccessible > SAL_CALL OConnectionLineAccess::getAccessibleAtPoint( const awt::Point& /*_aPoint*/ ) throw (RuntimeException) + { + return Reference< XAccessible >(); + } + // ----------------------------------------------------------------------------- + awt::Rectangle SAL_CALL OConnectionLineAccess::getBounds( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + Rectangle aRect(m_pLine ? m_pLine->GetBoundingRect() : Rectangle()); + return awt::Rectangle(aRect.getX(),aRect.getY(),aRect.getWidth(),aRect.getHeight()); + } + // ----------------------------------------------------------------------------- + awt::Point SAL_CALL OConnectionLineAccess::getLocation( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + Point aPoint(m_pLine ? m_pLine->GetBoundingRect().TopLeft() : Point()); + return awt::Point(aPoint.X(),aPoint.Y()); + } + // ----------------------------------------------------------------------------- + awt::Point SAL_CALL OConnectionLineAccess::getLocationOnScreen( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + Point aPoint(m_pLine ? m_pLine->GetParent()->ScreenToOutputPixel(m_pLine->GetBoundingRect().TopLeft()) : Point()); + return awt::Point(aPoint.X(),aPoint.Y()); + } + // ----------------------------------------------------------------------------- + awt::Size SAL_CALL OConnectionLineAccess::getSize( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + Size aSize(m_pLine ? m_pLine->GetBoundingRect().GetSize() : Size()); + return awt::Size(aSize.Width(),aSize.Height()); + } + // ----------------------------------------------------------------------------- + sal_Bool SAL_CALL OConnectionLineAccess::isShowing( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return m_pLine ? m_pLine->GetParent()->GetWindowRegionPixel().IsInside(m_pLine->GetBoundingRect()) : sal_False; + } + // ----------------------------------------------------------------------------- + sal_Bool SAL_CALL OConnectionLineAccess::isVisible( ) throw (RuntimeException) + { + return sal_True; + } + // ----------------------------------------------------------------------------- + sal_Bool SAL_CALL OConnectionLineAccess::isFocusTraversable( ) throw (RuntimeException) + { + return sal_True; + } + // ----------------------------------------------------------------------------- + // XAccessibleRelationSet + // ----------------------------------------------------------------------------- + sal_Int32 SAL_CALL OConnectionLineAccess::getRelationCount( ) throw (RuntimeException) + { + return 1; + } + // ----------------------------------------------------------------------------- + AccessibleRelation SAL_CALL OConnectionLineAccess::getRelation( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if( nIndex < 0 || nIndex >= getRelationCount() ) + throw IndexOutOfBoundsException(); + + Sequence< Reference<XInterface> > aSeq(m_pLine ? 2 : 0); + if( m_pLine ) + { + aSeq[0] = m_pLine->GetSourceWin()->GetAccessible(); + aSeq[1] = m_pLine->GetDestWin()->GetAccessible(); + } + + return AccessibleRelation(AccessibleRelationType::CONTROLLED_BY,aSeq); + } + // ----------------------------------------------------------------------------- + sal_Bool SAL_CALL OConnectionLineAccess::containsRelation( sal_Int16 aRelationType ) throw (RuntimeException) + { + return AccessibleRelationType::CONTROLLED_BY == aRelationType; + } + // ----------------------------------------------------------------------------- + AccessibleRelation SAL_CALL OConnectionLineAccess::getRelationByType( sal_Int16 aRelationType ) throw (RuntimeException) + { + if( AccessibleRelationType::CONTROLLED_BY == aRelationType ) + return getRelation(0); + return AccessibleRelation(); + } + // ----------------------------------------------------------------------------- + Reference< XAccessible > OTableConnection::CreateAccessible() + { + return new OConnectionLineAccess(this); + } + // ----------------------------------------------------------------------------- + OTableConnection::~OTableConnection() + { + DBG_DTOR(OTableConnection,NULL); + ////////////////////////////////////////////////////////////////////// + // clear vector + clearLineData(); + } + // ----------------------------------------------------------------------------- + sal_Bool OConnectionLineAccess::isEditable() const + { + + return m_pLine ? !m_pLine->GetParent()->getDesignView()->getController().isReadOnly() : sal_False; + } + // ----------------------------------------------------------------------------- + Reference< XAccessibleContext > SAL_CALL OConnectionLineAccess::getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException) + { + return this; + } + // ----------------------------------------------------------------------------- +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/ConnectionLineData.cxx b/dbaccess/source/ui/querydesign/ConnectionLineData.cxx new file mode 100644 index 000000000000..49360b0959b5 --- /dev/null +++ b/dbaccess/source/ui/querydesign/ConnectionLineData.cxx @@ -0,0 +1,104 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "ConnectionLineData.hxx" +#include <tools/debug.hxx> + + +using namespace dbaui; +DBG_NAME(OConnectionLineData) +//================================================================== +//class OConnectionLineData +//================================================================== +//------------------------------------------------------------------------ +OConnectionLineData::OConnectionLineData() +{ + DBG_CTOR(OConnectionLineData,NULL); +} + +//------------------------------------------------------------------------ +OConnectionLineData::OConnectionLineData( const ::rtl::OUString& rSourceFieldName, const ::rtl::OUString& rDestFieldName ) + :m_aSourceFieldName( rSourceFieldName ) + ,m_aDestFieldName( rDestFieldName ) +{ + DBG_CTOR(OConnectionLineData,NULL); +} + +//------------------------------------------------------------------------ +OConnectionLineData::OConnectionLineData( const OConnectionLineData& rConnLineData ) + : ::salhelper::SimpleReferenceObject() +{ + DBG_CTOR(OConnectionLineData,NULL); + *this = rConnLineData; +} + +//------------------------------------------------------------------------ +OConnectionLineData::~OConnectionLineData() +{ + DBG_DTOR(OConnectionLineData,NULL); +} + +//------------------------------------------------------------------------ +void OConnectionLineData::CopyFrom(const OConnectionLineData& rSource) +{ + *this = rSource; + // hier ziehe ich mich auf das (nicht-virtuelle) operator= zurueck, das nur meine Members kopiert +} + +//------------------------------------------------------------------------ +OConnectionLineData& OConnectionLineData::operator=( const OConnectionLineData& rConnLineData ) +{ + if (&rConnLineData == this) + return *this; + + m_aSourceFieldName = rConnLineData.GetSourceFieldName(); + m_aDestFieldName = rConnLineData.GetDestFieldName(); + + return *this; +} + +//------------------------------------------------------------------------ +bool OConnectionLineData::Reset() +{ + m_aDestFieldName = m_aSourceFieldName = ::rtl::OUString(); + return true; +} +// ----------------------------------------------------------------------------- +namespace dbaui +{ +//------------------------------------------------------------------------- +bool operator==(const OConnectionLineData& lhs, const OConnectionLineData& rhs) +{ + return (lhs.m_aSourceFieldName == rhs.m_aSourceFieldName) + && (lhs.m_aDestFieldName == rhs.m_aDestFieldName); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/JAccess.cxx b/dbaccess/source/ui/querydesign/JAccess.cxx new file mode 100644 index 000000000000..90feae92b25d --- /dev/null +++ b/dbaccess/source/ui/querydesign/JAccess.cxx @@ -0,0 +1,131 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "JAccess.hxx" +#include "JoinTableView.hxx" +#include "JoinTableView.hxx" +#include "TableWindow.hxx" +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include "JoinDesignView.hxx" +#include "JoinController.hxx" +#include "TableConnection.hxx" + +namespace dbaui +{ + using namespace ::com::sun::star::accessibility; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + + OJoinDesignViewAccess::OJoinDesignViewAccess(OJoinTableView* _pTableView) + :VCLXAccessibleComponent(_pTableView->GetComponentInterface().is() ? _pTableView->GetWindowPeer() : NULL) + ,m_pTableView(_pTableView) + { + } + // ----------------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OJoinDesignViewAccess::getImplementationName() throw(RuntimeException) + { + return getImplementationName_Static(); + } + // ----------------------------------------------------------------------------- + ::rtl::OUString OJoinDesignViewAccess::getImplementationName_Static(void) throw( RuntimeException ) + { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.dbu.JoinViewAccessibility")); + } + // ----------------------------------------------------------------------------- + void OJoinDesignViewAccess::clearTableView() + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_pTableView = NULL; + } + // ----------------------------------------------------------------------------- + // XAccessibleContext + sal_Int32 SAL_CALL OJoinDesignViewAccess::getAccessibleChildCount( ) throw (RuntimeException) + { + // TODO may be this will change to only visible windows + // this is the same assumption mt implements + ::osl::MutexGuard aGuard( m_aMutex ); + sal_Int32 nChildCount = 0; + if ( m_pTableView ) + nChildCount = m_pTableView->GetTabWinCount() + m_pTableView->getTableConnections()->size(); + return nChildCount; + } + // ----------------------------------------------------------------------------- + Reference< XAccessible > SAL_CALL OJoinDesignViewAccess::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException,RuntimeException) + { + Reference< XAccessible > aRet; + ::osl::MutexGuard aGuard( m_aMutex ); + if(i >= 0 && i < getAccessibleChildCount() && m_pTableView ) + { + // check if we should return a table window or a connection + sal_Int32 nTableWindowCount = m_pTableView->GetTabWinCount(); + if( i < nTableWindowCount ) + { + OJoinTableView::OTableWindowMap::iterator aIter = m_pTableView->GetTabWinMap()->begin(); + for (sal_Int32 j=i; j; ++aIter,--j) + ; + aRet = aIter->second->GetAccessible(); + } + else if( size_t(i - nTableWindowCount) < m_pTableView->getTableConnections()->size() ) + aRet = (*m_pTableView->getTableConnections())[i - nTableWindowCount]->GetAccessible(); + } + else + throw IndexOutOfBoundsException(); + return aRet; + } + // ----------------------------------------------------------------------------- + sal_Bool OJoinDesignViewAccess::isEditable() const + { + return m_pTableView && !m_pTableView->getDesignView()->getController().isReadOnly(); + } + // ----------------------------------------------------------------------------- + sal_Int16 SAL_CALL OJoinDesignViewAccess::getAccessibleRole( ) throw (RuntimeException) + { + return AccessibleRole::VIEW_PORT; + } + // ----------------------------------------------------------------------------- + Reference< XAccessibleContext > SAL_CALL OJoinDesignViewAccess::getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException) + { + return this; + } + // ----------------------------------------------------------------------------- + // ----------------------------------------------------------------------------- + // XInterface + // ----------------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( OJoinDesignViewAccess, VCLXAccessibleComponent, OJoinDesignViewAccess_BASE ) + // ----------------------------------------------------------------------------- + // XTypeProvider + // ----------------------------------------------------------------------------- + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OJoinDesignViewAccess, VCLXAccessibleComponent, OJoinDesignViewAccess_BASE ) +} + +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/JoinController.cxx b/dbaccess/source/ui/querydesign/JoinController.cxx new file mode 100644 index 000000000000..759616d4c05c --- /dev/null +++ b/dbaccess/source/ui/querydesign/JoinController.cxx @@ -0,0 +1,474 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include <sfx2/sfxsids.hrc> +#include "dbu_qry.hrc" +#include "browserids.hxx" +#include <comphelper/types.hxx> +#include "dbustrings.hrc" +#include <connectivity/dbtools.hxx> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <comphelper/extract.hxx> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> +#include <com/sun/star/sdbcx/XDrop.hpp> +#include <com/sun/star/sdbcx/XAlterTable.hpp> +#include <com/sun/star/sdbcx/XAppend.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/sdbc/SQLWarning.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <connectivity/dbexception.hxx> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <comphelper/streamsection.hxx> +#include <comphelper/basicio.hxx> +#include <comphelper/seqstream.hxx> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include "sqlmessage.hxx" +#include "JoinController.hxx" +#include <vcl/msgbox.hxx> +#include "TableWindowData.hxx" +#include "TableWindow.hxx" +#include "TableConnectionData.hxx" +#include "adtabdlg.hxx" +#include <vcl/waitobj.hxx> +#include <vcl/svapp.hxx> +#include <osl/mutex.hxx> +#include "UITools.hxx" + +#include <boost/optional.hpp> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::dbtools; +using namespace ::comphelper; + +// ............................................................................. +namespace dbaui +{ +// ............................................................................. + +// ============================================================================= +// = AddTableDialogContext +// ============================================================================= +class AddTableDialogContext : public IAddTableDialogContext +{ + OJoinController& m_rController; + +public: + AddTableDialogContext( OJoinController& _rController ) + :m_rController( _rController ) + { + } + + // IAddTableDialogContext + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > + getConnection() const; + virtual bool allowViews() const; + virtual bool allowQueries() const; + virtual bool allowAddition() const; + virtual void addTableWindow( const String& _rQualifiedTableName, const String& _rAliasName ); + virtual void onWindowClosing( const Window* _pWindow ); + +private: + OJoinTableView* getTableView() const; +}; + +// ----------------------------------------------------------------------------- +Reference< XConnection > AddTableDialogContext::getConnection() const +{ + return m_rController.getConnection(); +} + +// ----------------------------------------------------------------------------- +bool AddTableDialogContext::allowViews() const +{ + return m_rController.allowViews(); +} + +// ----------------------------------------------------------------------------- +bool AddTableDialogContext::allowQueries() const +{ + return m_rController.allowQueries(); +} + +// ----------------------------------------------------------------------------- +bool AddTableDialogContext::allowAddition() const +{ + return const_cast< OJoinController& >( m_rController ).getJoinView()->getTableView()->IsAddAllowed(); +} + +// ----------------------------------------------------------------------------- +void AddTableDialogContext::addTableWindow( const String& _rQualifiedTableName, const String& _rAliasName ) +{ + getTableView()->AddTabWin( _rQualifiedTableName, _rAliasName, TRUE ); +} + +// ----------------------------------------------------------------------------- +void AddTableDialogContext::onWindowClosing( const Window* _pWindow ) +{ + if ( !m_rController.getView() ) + return; + + ::dbaui::notifySystemWindow( + m_rController.getView(), const_cast< Window* >( _pWindow ), ::comphelper::mem_fun( &TaskPaneList::RemoveWindow ) ); + + m_rController.InvalidateFeature( ID_BROWSER_ADDTABLE ); + m_rController.getView()->GrabFocus(); +} + +// ----------------------------------------------------------------------------- +OJoinTableView* AddTableDialogContext::getTableView() const +{ + if ( m_rController.getJoinView() ) + return m_rController.getJoinView()->getTableView(); + return NULL; +} + +// ============================================================================= +// = OJoinController +// ============================================================================= + +DBG_NAME(OJoinController) +// ----------------------------------------------------------------------------- +OJoinController::OJoinController(const Reference< XMultiServiceFactory >& _rM) + :OJoinController_BASE(_rM) + ,m_pAddTableDialog(NULL) +{ + DBG_CTOR(OJoinController,NULL); +} +// ----------------------------------------------------------------------------- +OJoinController::~OJoinController() +{ + DBG_DTOR(OJoinController,NULL); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL OJoinController::disposing( const EventObject& _rSource ) throw(RuntimeException) +{ + OJoinController_BASE::disposing( _rSource ); +} + +// ----------------------------------------------------------------------------- +OJoinDesignView* OJoinController::getJoinView() +{ + return static_cast< OJoinDesignView* >( getView() ); +} + +// ----------------------------------------------------------------------------- +void OJoinController::disposing() +{ + { + ::std::auto_ptr< Window > pEnsureDelete( m_pAddTableDialog ); + m_pAddTableDialog = NULL; + } + + OJoinController_BASE::disposing(); + + clearView(); + + m_vTableConnectionData.clear(); + m_vTableData.clear(); +} +// ----------------------------------------------------------------------------- +void OJoinController::reconnect( sal_Bool _bUI ) +{ + OJoinController_BASE::reconnect( _bUI ); + if ( isConnected() && m_pAddTableDialog ) + m_pAddTableDialog->Update(); +} + +// ----------------------------------------------------------------------------- +void OJoinController::impl_onModifyChanged() +{ + OJoinController_BASE::impl_onModifyChanged(); + InvalidateFeature( SID_RELATION_ADD_RELATION ); +} +// ----------------------------------------------------------------------------- +void OJoinController::SaveTabWinPosSize(OTableWindow* pTabWin, long nOffsetX, long nOffsetY) +{ + // die Daten zum Fenster + TTableWindowData::value_type pData = pTabWin->GetData(); + OSL_ENSURE(pData != NULL, "SaveTabWinPosSize : TabWin hat keine Daten !"); + + // Position & Size der Daten neu setzen (aus den aktuellen Fenster-Parametern) + Point aPos = pTabWin->GetPosPixel(); + aPos.X() += nOffsetX; + aPos.Y() += nOffsetY; + pData->SetPosition(aPos); + pData->SetSize(pTabWin->GetSizePixel()); + +} +// ----------------------------------------------------------------------------- +FeatureState OJoinController::GetState(sal_uInt16 _nId) const +{ + FeatureState aReturn; + // (disabled automatically) + aReturn.bEnabled = sal_True; + + switch (_nId) + { + case ID_BROWSER_EDITDOC: + aReturn.bChecked = isEditable(); + break; + case ID_BROWSER_ADDTABLE: + aReturn.bEnabled = ( getView() != NULL ) + && const_cast< OJoinController* >( this )->getJoinView()->getTableView()->IsAddAllowed(); + aReturn.bChecked = aReturn.bEnabled && m_pAddTableDialog != NULL && m_pAddTableDialog->IsVisible() ; + if ( aReturn.bEnabled ) + aReturn.sTitle = OAddTableDlg::getDialogTitleForContext( impl_getDialogContext() ); + break; + + default: + aReturn = OJoinController_BASE::GetState(_nId); + } + return aReturn; +} + +// ----------------------------------------------------------------------------- +AddTableDialogContext& OJoinController::impl_getDialogContext() const +{ + if ( !m_pDialogContext.get() ) + { + OJoinController* pNonConstThis = const_cast< OJoinController* >( this ); + pNonConstThis->m_pDialogContext.reset( new AddTableDialogContext( *pNonConstThis ) ); + } + return *m_pDialogContext; +} + +// ----------------------------------------------------------------------------- +void OJoinController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs) +{ + switch(_nId) + { + case ID_BROWSER_EDITDOC: + if(isEditable()) + { // the state should be changed to not editable + switch (saveModified()) + { + case RET_CANCEL: + // don't change anything here so return + return; + case RET_NO: + reset(); + setModified(sal_False); // and we are not modified yet + break; + default: + break; + } + } + setEditable(!isEditable()); + getJoinView()->setReadOnly(!isEditable()); + InvalidateAll(); + return; + case ID_BROWSER_ADDTABLE: + if ( !m_pAddTableDialog ) + m_pAddTableDialog = new OAddTableDlg( getView(), impl_getDialogContext() ); + + if ( m_pAddTableDialog->IsVisible() ) + { + m_pAddTableDialog->Show( FALSE ); + getView()->GrabFocus(); + } + else + { + { + WaitObject aWaitCursor( getView() ); + m_pAddTableDialog->Update(); + } + m_pAddTableDialog->Show( TRUE ); + ::dbaui::notifySystemWindow(getView(),m_pAddTableDialog,::comphelper::mem_fun(&TaskPaneList::AddWindow)); + } + break; + default: + OJoinController_BASE::Execute(_nId,aArgs); + } + InvalidateFeature(_nId); +} +// ----------------------------------------------------------------------------- +void OJoinController::SaveTabWinsPosSize( OJoinTableView::OTableWindowMap* pTabWinList, long nOffsetX, long nOffsetY ) +{ + // Das Loeschen und Neuanlegen der alten Implementation ist unter dem aktuellen Modell nicht mehr richtig : Die TabWins + // habe einen Zeiger auf ihre Daten, verwaltet werden sie aber von mir. Wenn ich die alten loesche, haben die TabWins + // ploetzlich Zeiger auf nicht mehr existente Objekte. + // Wenn die TabWins ein SetData haetten, koennte ich mir das sparen ... haben sie aber nicht, ausserdem muesste ich dann immer + // noch Informationen, die sich eigentlich nicht geaendert haben, auch neu setzen. + // Also loesche ich die TabWinDatas nicht, sondern aktualisiere sie nur. + DBG_ASSERT(m_vTableData.size() == pTabWinList->size(), + "OJoinController::SaveTabWinsPosSize : inkonsistenter Zustand : sollte genausviel TabWinDatas haben wie TabWins !"); + + OJoinTableView::OTableWindowMap::iterator aIter = pTabWinList->begin(); + OJoinTableView::OTableWindowMap::iterator aEnd = pTabWinList->end(); + for(;aIter != aEnd;++aIter) + SaveTabWinPosSize(aIter->second, nOffsetX, nOffsetY); +} +// ----------------------------------------------------------------------------- +void OJoinController::removeConnectionData(const TTableConnectionData::value_type& _pData) +{ + m_vTableConnectionData.erase( ::std::remove(m_vTableConnectionData.begin(),m_vTableConnectionData.end(),_pData),m_vTableConnectionData.end()); +} +// ----------------------------------------------------------------------------- +void OJoinController::describeSupportedFeatures() +{ + OJoinController_BASE::describeSupportedFeatures(); + implDescribeSupportedFeature( ".uno:Redo", ID_BROWSER_REDO, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVEDOC, CommandGroup::DOCUMENT ); + implDescribeSupportedFeature( ".uno:Undo", ID_BROWSER_UNDO, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:AddTable", ID_BROWSER_ADDTABLE,CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:EditDoc", ID_BROWSER_EDITDOC, CommandGroup::EDIT ); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OJoinController::suspend(sal_Bool _bSuspend) throw( RuntimeException ) +{ + if ( getBroadcastHelper().bInDispose || getBroadcastHelper().bDisposed ) + return sal_True; + + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( getMutex() ); + if ( getView() && getView()->IsInModalMode() ) + return sal_False; + sal_Bool bCheck = sal_True; + if ( _bSuspend ) + { + bCheck = saveModified() != RET_CANCEL; + if ( bCheck ) + OSingleDocumentController::suspend(_bSuspend); + } + return bCheck; +} +// ----------------------------------------------------------------------------- +void OJoinController::loadTableWindows( const ::comphelper::NamedValueCollection& i_rViewSettings ) +{ + m_vTableData.clear(); + + m_aMinimumTableViewSize = Point(); + + Sequence< PropertyValue > aWindowData; + aWindowData = i_rViewSettings.getOrDefault( "Tables", aWindowData ); + + const PropertyValue* pTablesIter = aWindowData.getConstArray(); + const PropertyValue* pTablesEnd = pTablesIter + aWindowData.getLength(); + for ( ; pTablesIter != pTablesEnd; ++pTablesIter ) + { + ::comphelper::NamedValueCollection aSingleTableData( pTablesIter->Value ); + loadTableWindow( aSingleTableData ); + } + if ( m_aMinimumTableViewSize != Point() ) + { + getJoinView()->getScrollHelper()->resetRange( m_aMinimumTableViewSize ); + } +} + +// ----------------------------------------------------------------------------- +void OJoinController::loadTableWindow( const ::comphelper::NamedValueCollection& i_rTableWindowSettings ) +{ + sal_Int32 nX = -1, nY = -1, nHeight = -1, nWidth = -1; + + ::rtl::OUString sComposedName,sTableName,sWindowName; + sal_Bool bShowAll = false; + + sComposedName = i_rTableWindowSettings.getOrDefault( "ComposedName", sComposedName ); + sTableName = i_rTableWindowSettings.getOrDefault( "TableName", sTableName ); + sWindowName = i_rTableWindowSettings.getOrDefault( "WindowName", sWindowName ); + nY = i_rTableWindowSettings.getOrDefault( "WindowTop", nY ); + nX = i_rTableWindowSettings.getOrDefault( "WindowLeft", nX ); + nWidth = i_rTableWindowSettings.getOrDefault( "WindowWidth", nWidth ); + nHeight = i_rTableWindowSettings.getOrDefault( "WindowHeight", nHeight ); + bShowAll = i_rTableWindowSettings.getOrDefault( "ShowAll", bShowAll ); + + TTableWindowData::value_type pData = createTableWindowData(sComposedName,sTableName,sWindowName); + if ( pData ) + { + pData->SetPosition(Point(nX,nY)); + pData->SetSize( Size( nWidth, nHeight ) ); + pData->ShowAll(bShowAll); + m_vTableData.push_back(pData); + if ( m_aMinimumTableViewSize.X() < (nX+nWidth) ) + m_aMinimumTableViewSize.X() = (nX+nWidth); + if ( m_aMinimumTableViewSize.Y() < (nY+nHeight) ) + m_aMinimumTableViewSize.Y() = (nY+nHeight); + } +} +// ----------------------------------------------------------------------------- +void OJoinController::saveTableWindows( ::comphelper::NamedValueCollection& o_rViewSettings ) const +{ + if ( !m_vTableData.empty() ) + { + ::comphelper::NamedValueCollection aAllTablesData; + + TTableWindowData::const_iterator aIter = m_vTableData.begin(); + TTableWindowData::const_iterator aEnd = m_vTableData.end(); + for ( sal_Int32 i = 1; aIter != aEnd; ++aIter, ++i ) + { + ::comphelper::NamedValueCollection aWindowData; + aWindowData.put( "ComposedName", (*aIter)->GetComposedName() ); + aWindowData.put( "TableName", (*aIter)->GetTableName() ); + aWindowData.put( "WindowName", (*aIter)->GetWinName() ); + aWindowData.put( "WindowTop", static_cast<sal_Int32>((*aIter)->GetPosition().Y()) ); + aWindowData.put( "WindowLeft", static_cast<sal_Int32>((*aIter)->GetPosition().X()) ); + aWindowData.put( "WindowWidth", static_cast<sal_Int32>((*aIter)->GetSize().Width()) ); + aWindowData.put( "WindowHeight", static_cast<sal_Int32>((*aIter)->GetSize().Height()) ); + aWindowData.put( "ShowAll", (*aIter)->IsShowAll() ); + + const ::rtl::OUString sTableName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Table" ) ) + ::rtl::OUString::valueOf( i ) ); + aAllTablesData.put( sTableName, aWindowData.getPropertyValues() ); + } + + o_rViewSettings.put( "Tables", aAllTablesData.getPropertyValues() ); + } +} +// ----------------------------------------------------------------------------- +TTableWindowData::value_type OJoinController::createTableWindowData(const ::rtl::OUString& _sComposedName,const ::rtl::OUString& _sTableName,const ::rtl::OUString& _sWindowName) +{ + OJoinDesignView* pView = getJoinView(); + if( pView ) + return pView->getTableView()->createTableWindowData(_sComposedName,_sTableName,_sWindowName); + OSL_ENSURE(0,"We should never ever reach this point!"); + + return TTableWindowData::value_type(); +} +// ............................................................................. +} // namespace dbaui +// ............................................................................. + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/JoinDesignView.cxx b/dbaccess/source/ui/querydesign/JoinDesignView.cxx new file mode 100644 index 000000000000..397bb804c829 --- /dev/null +++ b/dbaccess/source/ui/querydesign/JoinDesignView.cxx @@ -0,0 +1,128 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "JoinDesignView.hxx" +#include "JoinTableView.hxx" +#include "JoinController.hxx" +#include <svl/undo.hxx> +#include "adtabdlg.hxx" +#include <vcl/svapp.hxx> +#include <vcl/msgbox.hxx> +#include "browserids.hxx" +#include "dbu_qry.hrc" +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include "TableConnection.hxx" +#include "ConnectionLine.hxx" +#include "ConnectionLineData.hxx" +#include "TableConnectionData.hxx" +#include "dbustrings.hrc" +#include <comphelper/extract.hxx> +#include "UITools.hxx" +#include "JoinTableView.hxx" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; + +namespace dbaui +{ + +// ============================================================================= +// = OJoinDesignView +// ============================================================================= +// ----------------------------------------------------------------------------- +OJoinDesignView::OJoinDesignView(Window* _pParent, OJoinController& _rController,const Reference< XMultiServiceFactory >& _rFactory) + :ODataView( _pParent, _rController, _rFactory ) + ,m_pTableView(NULL) + ,m_rController( _rController ) +{ + m_pScrollWindow = new OScrollWindowHelper(this); +} +// ----------------------------------------------------------------------------- +OJoinDesignView::~OJoinDesignView() +{ + ::std::auto_ptr<Window> aT3(m_pScrollWindow); + m_pScrollWindow = NULL; + ::std::auto_ptr<Window> aT2(m_pTableView); + m_pTableView = NULL; +} +// ------------------------------------------------------------------------- +void OJoinDesignView::Construct() +{ + m_pScrollWindow->setTableView(m_pTableView); + m_pScrollWindow->Show(); + m_pTableView->Show(); + + SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor()) ); + + ODataView::Construct(); +} +// ----------------------------------------------------------------------------- +void OJoinDesignView::initialize() +{ +} +// ------------------------------------------------------------------------- +void OJoinDesignView::resizeDocumentView(Rectangle& _rPlayground) +{ + m_pScrollWindow->SetPosSizePixel( _rPlayground.TopLeft(), _rPlayground.GetSize() ); + + // just for completeness: there is no space left, we occupied it all ... + _rPlayground.SetPos( _rPlayground.BottomRight() ); + _rPlayground.SetSize( Size( 0, 0 ) ); +} +// ----------------------------------------------------------------------------- +void OJoinDesignView::setReadOnly(sal_Bool /*_bReadOnly*/) +{ +} +// ----------------------------------------------------------------------------- +void OJoinDesignView::SaveTabWinUIConfig(OTableWindow* pWin) +{ + getController().SaveTabWinPosSize(pWin, m_pScrollWindow->GetHScrollBar()->GetThumbPos(), m_pScrollWindow->GetVScrollBar()->GetThumbPos()); +} +// ----------------------------------------------------------------------------- +void OJoinDesignView::KeyInput( const KeyEvent& rEvt ) +{ + if ( m_pTableView && m_pTableView->IsVisible() ) + m_pTableView->KeyInput( rEvt ); + else + ODataView::KeyInput(rEvt); +} +// ----------------------------------------------------------------------------- + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/JoinExchange.cxx b/dbaccess/source/ui/querydesign/JoinExchange.cxx new file mode 100644 index 000000000000..75d69afa5b09 --- /dev/null +++ b/dbaccess/source/ui/querydesign/JoinExchange.cxx @@ -0,0 +1,179 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "JoinExchange.hxx" +#include <sot/formats.hxx> +#include <svx/dbexch.hrc> +#include <cppuhelper/typeprovider.hxx> +#include <sot/formats.hxx> + +namespace dbaui +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::datatransfer; + + String OJoinExchObj::m_sJoinFormat; + //================================================================== + // class OJoinExchObj + //================================================================== + DBG_NAME(OJoinExchObj) + //------------------------------------------------------------------------ + OJoinExchObj::OJoinExchObj(const OJoinExchangeData& jxdSource,sal_Bool _bFirstEntry) + :m_bFirstEntry(_bFirstEntry) + ,m_jxdSourceDescription(jxdSource) + ,m_pDragListener(NULL) + { + DBG_CTOR(OJoinExchObj,NULL); + // Verfuegbare Typen in Liste einfuegen + } + + //------------------------------------------------------------------------ + OJoinExchObj::~OJoinExchObj() + { + DBG_DTOR(OJoinExchObj,NULL); + } + + //------------------------------------------------------------------------ + void OJoinExchObj::StartDrag( Window* _pWindow, sal_Int8 _nDragSourceActions, IDragTransferableListener* _pListener ) + { + m_pDragListener = _pListener; + TransferableHelper::StartDrag(_pWindow, _nDragSourceActions); + } + + //------------------------------------------------------------------------ + void OJoinExchObj::DragFinished( sal_Int8 /*nDropAction*/ ) + { + if (m_pDragListener) + m_pDragListener->dragFinished(); + m_pDragListener = NULL; + } + + //------------------------------------------------------------------------ + sal_Bool OJoinExchObj::isFormatAvailable( const DataFlavorExVector& _rFormats ,SotFormatStringId _nSlotID) + { + DataFlavorExVector::const_iterator aCheckEnd = _rFormats.end(); + for ( DataFlavorExVector::const_iterator aCheck = _rFormats.begin(); + aCheck != aCheckEnd; + ++aCheck + ) + { + if ( _nSlotID == aCheck->mnSotId ) + return sal_True; + } + return sal_False; + } + + //------------------------------------------------------------------------ + OJoinExchangeData OJoinExchObj::GetSourceDescription(const Reference< XTransferable >& _rxObject) + { + OJoinExchangeData aReturn; + Reference< XUnoTunnel > xTunnel(_rxObject, UNO_QUERY); + if (xTunnel.is()) + { + OJoinExchObj* pImplementation = reinterpret_cast<OJoinExchObj*>(xTunnel->getSomething(getUnoTunnelImplementationId())); + if (pImplementation) + aReturn = pImplementation->m_jxdSourceDescription; + } + return aReturn; + } + + //------------------------------------------------------------------------ + Sequence< sal_Int8 > OJoinExchObj::getUnoTunnelImplementationId() + { + static ::cppu::OImplementationId * pId = 0; + if (! pId) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if (! pId) + { + static ::cppu::OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); + } + + //------------------------------------------------------------------------ + sal_Int64 SAL_CALL OJoinExchObj::getSomething( const Sequence< sal_Int8 >& _rIdentifier ) throw(RuntimeException) + { + if (_rIdentifier.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), _rIdentifier.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + return 0; + } + + //------------------------------------------------------------------------ + void OJoinExchObj::AddSupportedFormats() + { + AddFormat( SOT_FORMATSTR_ID_SBA_JOIN ); + if ( m_bFirstEntry ) + AddFormat( SOT_FORMATSTR_ID_SBA_TABID ); + } + + //------------------------------------------------------------------------ + sal_Bool OJoinExchObj::GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor ) + { + sal_uInt32 nFormat = SotExchange::GetFormat(rFlavor); + if ( SOT_FORMATSTR_ID_SBA_JOIN == nFormat ) + // this is a HACK + // we don't really copy our data, the instances using us have to call GetSourceDescription .... + // if, one day, we have a _lot_ of time, this hack should be removed .... + return sal_True; + + return sal_False; + } + + //------------------------------------------------------------------------ + Any SAL_CALL OJoinExchObj::queryInterface( const Type& _rType ) throw(RuntimeException) + { + Any aReturn = TransferableHelper::queryInterface(_rType); + if (!aReturn.hasValue()) + aReturn = OJoinExchObj_Base::queryInterface(_rType); + return aReturn; + } + + //------------------------------------------------------------------------ + void SAL_CALL OJoinExchObj::acquire( ) throw() + { + TransferableHelper::acquire( ); + } + + //------------------------------------------------------------------------ + void SAL_CALL OJoinExchObj::release( ) throw() + { + TransferableHelper::release( ); + } + + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/JoinTableView.cxx b/dbaccess/source/ui/querydesign/JoinTableView.cxx new file mode 100644 index 000000000000..017347595520 --- /dev/null +++ b/dbaccess/source/ui/querydesign/JoinTableView.cxx @@ -0,0 +1,1718 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "JoinTableView.hxx" +#include <tools/debug.hxx> +#include "querycontroller.hxx" +#include "JoinDesignView.hxx" +#include "dbu_qry.hrc" +#include "TableWindow.hxx" +#include "TableWindowListBox.hxx" +#include "TableConnection.hxx" +#include "TableConnectionData.hxx" +#include "ConnectionLine.hxx" +#include "ConnectionLineData.hxx" +#include "browserids.hxx" +#include <svl/urlbmk.hxx> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include "QueryMoveTabWinUndoAct.hxx" +#include "QuerySizeTabWinUndoAct.hxx" +#include <vcl/svapp.hxx> +#include "TableWindowData.hxx" +#include "JAccess.hxx" +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include "UITools.hxx" +#include <cppuhelper/exc_hlp.hxx> +#include <tools/diagnose_ex.h> +#include <boost/bind.hpp> +#include <algorithm> +#include <functional> + +using namespace dbaui; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + +#define LINE_SIZE 50 +//////////////////////////////////////////////////////////////// +// Konstanten fuer das Fensterlayout +#define TABWIN_SPACING_X 17 +#define TABWIN_SPACING_Y 17 + +#define TABWIN_WIDTH_STD 120 +#define TABWIN_HEIGHT_STD 120 + +DBG_NAME(OScrollWindowHelper) +OScrollWindowHelper::OScrollWindowHelper( Window* pParent) : Window( pParent) + ,m_aHScrollBar( this, WB_HSCROLL|WB_REPEAT|WB_DRAG ) + ,m_aVScrollBar( this, WB_VSCROLL|WB_REPEAT|WB_DRAG ) + ,m_pCornerWindow(new ScrollBarBox(this, WB_3DLOOK)) + ,m_pTableView(NULL) +{ + DBG_CTOR(OScrollWindowHelper,NULL); + + ////////////////////////////////////////////////////////////////////// + // ScrollBars + + GetHScrollBar()->SetRange( Range(0, 1000) ); + GetVScrollBar()->SetRange( Range(0, 1000) ); + + GetHScrollBar()->SetLineSize( LINE_SIZE ); + GetVScrollBar()->SetLineSize( LINE_SIZE ); + + GetHScrollBar()->Show(); + GetVScrollBar()->Show(); + m_pCornerWindow->Show(); + + // normally we should be SCROLL_PANE + SetAccessibleRole(AccessibleRole::SCROLL_PANE); +} + +// ----------------------------------------------------------------------------- +OScrollWindowHelper::~OScrollWindowHelper() +{ + DBG_DTOR(OScrollWindowHelper,NULL); + ::std::auto_ptr<Window> aTemp(m_pCornerWindow); + m_pCornerWindow = NULL; + m_pTableView = NULL; +} + +// ----------------------------------------------------------------------------- +void OScrollWindowHelper::setTableView(OJoinTableView* _pTableView) +{ + m_pTableView = _pTableView; + ////////////////////////////////////////////////////////////////////// + // ScrollBars + GetHScrollBar()->SetScrollHdl( LINK(m_pTableView, OJoinTableView, ScrollHdl) ); + GetVScrollBar()->SetScrollHdl( LINK(m_pTableView, OJoinTableView, ScrollHdl) ); +} +// ----------------------------------------------------------------------------- +void OScrollWindowHelper::resetRange(const Point& _aSize) +{ + Point aPos = PixelToLogic(_aSize); + GetHScrollBar()->SetRange( Range(0, aPos.X() + TABWIN_SPACING_X) ); + GetVScrollBar()->SetRange( Range(0, aPos.Y() + TABWIN_SPACING_Y) ); +} +//------------------------------------------------------------------------------ +void OScrollWindowHelper::Resize() +{ + Window::Resize(); + + Size aTotalOutputSize = GetOutputSizePixel(); + long nHScrollHeight = GetHScrollBar()->GetSizePixel().Height(); + long nVScrollWidth = GetVScrollBar()->GetSizePixel().Width(); + + GetHScrollBar()->SetPosSizePixel( + Point( 0, aTotalOutputSize.Height()-nHScrollHeight ), + Size( aTotalOutputSize.Width()-nVScrollWidth, nHScrollHeight ) + ); + + GetVScrollBar()->SetPosSizePixel( + Point( aTotalOutputSize.Width()-nVScrollWidth, 0 ), + Size( nVScrollWidth, aTotalOutputSize.Height()-nHScrollHeight ) + ); + + m_pCornerWindow->SetPosSizePixel( + Point( aTotalOutputSize.Width() - nVScrollWidth, aTotalOutputSize.Height() - nHScrollHeight), + Size( nVScrollWidth, nHScrollHeight ) + ); + + GetHScrollBar()->SetPageSize( aTotalOutputSize.Width() ); + GetHScrollBar()->SetVisibleSize( aTotalOutputSize.Width() ); + + GetVScrollBar()->SetPageSize( aTotalOutputSize.Height() ); + GetVScrollBar()->SetVisibleSize( aTotalOutputSize.Height() ); + + // adjust the ranges of the scrollbars if neccessary + long lRange = GetHScrollBar()->GetRange().Max() - GetHScrollBar()->GetRange().Min(); + if (m_pTableView->GetScrollOffset().X() + aTotalOutputSize.Width() > lRange) + GetHScrollBar()->SetRangeMax(m_pTableView->GetScrollOffset().X() + aTotalOutputSize.Width() + GetHScrollBar()->GetRange().Min()); + + lRange = GetVScrollBar()->GetRange().Max() - GetVScrollBar()->GetRange().Min(); + if (m_pTableView->GetScrollOffset().Y() + aTotalOutputSize.Height() > lRange) + GetVScrollBar()->SetRangeMax(m_pTableView->GetScrollOffset().Y() + aTotalOutputSize.Height() + GetVScrollBar()->GetRange().Min()); + + m_pTableView->SetPosSizePixel(Point( 0, 0 ),Size( aTotalOutputSize.Width()-nVScrollWidth, aTotalOutputSize.Height()-nHScrollHeight )); +} +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +//================================================================== +// class OJoinTableView +//================================================================== + +DBG_NAME(OJoinTableView); +//------------------------------------------------------------------------------ +OJoinTableView::OJoinTableView( Window* pParent, OJoinDesignView* pView ) + :Window( pParent,WB_BORDER ) + ,DropTargetHelper(this) + ,m_aDragOffset( Point(0,0) ) + ,m_aScrollOffset( Point(0,0) ) + ,m_pDragWin( NULL ) + ,m_pSizingWin( NULL ) + ,m_pSelectedConn( NULL ) + ,m_bTrackingInitiallyMoved(FALSE) + ,m_pLastFocusTabWin(NULL) + ,m_pView( pView ) + ,m_pAccessible(NULL) +{ + DBG_CTOR(OJoinTableView,NULL); + SetSizePixel( Size(1000, 1000) ); + + InitColors(); + + m_aDragScrollTimer.SetTimeoutHdl(LINK(this, OJoinTableView, OnDragScrollTimer)); +} + +//------------------------------------------------------------------------------ +OJoinTableView::~OJoinTableView() +{ + DBG_DTOR(OJoinTableView,NULL); + if( m_pAccessible ) + { + m_pAccessible->clearTableView(); + m_pAccessible = NULL; + } + ////////////////////////////////////////////////////////////////////// + // Listen loeschen + clearLayoutInformation(); +} +//------------------------------------------------------------------------------ +IMPL_LINK( OJoinTableView, ScrollHdl, ScrollBar*, pScrollBar ) +{ + ////////////////////////////////////////////////////////////////////// + // Alle Fenster verschieben + ScrollPane( pScrollBar->GetDelta(), (pScrollBar == GetHScrollBar()), FALSE ); + + return 0; +} +//------------------------------------------------------------------------------ +void OJoinTableView::Resize() +{ + DBG_CHKTHIS(OJoinTableView,NULL); + Window::Resize(); + m_aOutputSize = GetSizePixel(); + + // tab win positions may not be up-to-date + if (m_aTableMap.empty()) + // no tab wins ... + return; + + // we have at least one table so resize it + m_aScrollOffset.X() = GetHScrollBar()->GetThumbPos(); + m_aScrollOffset.Y() = GetVScrollBar()->GetThumbPos(); + + OTableWindow* pCheck = m_aTableMap.begin()->second; + Point aRealPos = pCheck->GetPosPixel(); + Point aAssumedPos = pCheck->GetData()->GetPosition() - GetScrollOffset(); + + if (aRealPos == aAssumedPos) + // all ok + return; + + OTableWindowMapIterator aIter = m_aTableMap.begin(); + OTableWindowMapIterator aEnd = m_aTableMap.end(); + for(;aIter != aEnd;++aIter) + { + OTableWindow* pCurrent = aIter->second; + Point aPos(pCurrent->GetData()->GetPosition() - GetScrollOffset()); + pCurrent->SetPosPixel(aPos); + } +} +//------------------------------------------------------------------------------ +ULONG OJoinTableView::GetTabWinCount() +{ + DBG_CHKTHIS(OJoinTableView,NULL); + return m_aTableMap.size(); +} + +//------------------------------------------------------------------------------ +bool OJoinTableView::RemoveConnection( OTableConnection* _pConn,sal_Bool _bDelete ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + DeselectConn(_pConn); + + // to force a redraw + _pConn->InvalidateConnection(); + + m_pView->getController().removeConnectionData( _pConn->GetData() ); + + m_vTableConnection.erase( + ::std::find(m_vTableConnection.begin(),m_vTableConnection.end(),_pConn) ); + + modified(); + if ( m_pAccessible ) + m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD, + makeAny(_pConn->GetAccessible()), + Any()); + if ( _bDelete ) + { + delete _pConn; + } + + return true; +} + +//------------------------------------------------------------------------ +OTableWindow* OJoinTableView::GetTabWindow( const String& rName ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + OTableWindowMapIterator aIter = m_aTableMap.find(rName); + + return aIter == m_aTableMap.end() ? NULL : aIter->second; +} +// ----------------------------------------------------------------------------- +TTableWindowData::value_type OJoinTableView::createTableWindowData(const ::rtl::OUString& _rComposedName + ,const ::rtl::OUString& _sTableName + ,const ::rtl::OUString& _rWinName) +{ + TTableWindowData::value_type pData( CreateImpl(_rComposedName, _sTableName,_rWinName) ); + OJoinDesignView* pParent = getDesignView(); + try + { + if ( !pData->init(pParent->getController().getConnection(),allowQueries()) ) + { + if ( pData->isValid() ) + onNoColumns_throw(); + else + pData.reset(); + } + } + catch ( const SQLException& ) + { + ::dbaui::showError( ::dbtools::SQLExceptionInfo( ::cppu::getCaughtException() ), + pParent, pParent->getController().getORB() ); + } + catch( const WrappedTargetException& e ) + { + SQLException aSql; + if ( e.TargetException >>= aSql ) + ::dbaui::showError( ::dbtools::SQLExceptionInfo( aSql ), pParent, pParent->getController().getORB() ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return pData; +} +// ----------------------------------------------------------------------------- +OTableWindowData* OJoinTableView::CreateImpl(const ::rtl::OUString& _rComposedName + ,const ::rtl::OUString& _sTableName + ,const ::rtl::OUString& _rWinName) +{ + return new OTableWindowData( NULL,_rComposedName,_sTableName, _rWinName ); +} +//------------------------------------------------------------------------------ +void OJoinTableView::AddTabWin(const ::rtl::OUString& _rComposedName, const ::rtl::OUString& rWinName, BOOL /*bNewTable*/) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + OSL_ENSURE(_rComposedName.getLength(),"There must be a table name supplied!"); + + TTableWindowData::value_type pNewTabWinData(createTableWindowData( _rComposedName, rWinName,rWinName )); + + ////////////////////////////////////////////////////////////////// + // 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 + if(m_aTableMap.find(rWinName) != m_aTableMap.end()) + m_aTableMap[_rComposedName] = pNewTabWin; + else + m_aTableMap[rWinName] = pNewTabWin; + + SetDefaultTabWinPosSize( pNewTabWin ); + pNewTabWin->Show(); + + modified(); + if ( m_pAccessible ) + m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD, + Any(), + makeAny(pNewTabWin->GetAccessible())); + } + else + { + pNewTabWin->clearListBox(); + delete pNewTabWin; + } +} + +//------------------------------------------------------------------------------ +void OJoinTableView::RemoveTabWin( OTableWindow* pTabWin ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + ////////////////////////////////////////////////////////////////////// + // first delete all connections of this window to others + bool bRemove = true; + TTableWindowData::value_type pData = pTabWin->GetData(); + sal_Int32 nCount = m_vTableConnection.size(); + ::std::vector<OTableConnection*>::reverse_iterator aIter = m_vTableConnection.rbegin(); + while(aIter != m_vTableConnection.rend() && bRemove) + { + OTableConnection* pTabConn = (*aIter); + if( + ( pData == pTabConn->GetData()->getReferencingTable()) || + ( pData == pTabConn->GetData()->getReferencedTable()) + ) + { + bRemove = RemoveConnection( pTabConn ,sal_True); + aIter = m_vTableConnection.rbegin(); + } + else + ++aIter; + } + + ////////////////////////////////////////////////////////////////////// + // then delete the window itself + if ( bRemove ) + { + if ( m_pAccessible ) + m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD, + makeAny(pTabWin->GetAccessible()),Any() + ); + + pTabWin->Hide(); + OJoinController& rController = m_pView->getController(); + TTableWindowData::iterator aFind = ::std::find(rController.getTableWindowData()->begin(),rController.getTableWindowData()->end(),pData); + if(aFind != rController.getTableWindowData()->end()) + { + rController.getTableWindowData()->erase(aFind); + rController.setModified(sal_True); + } + + String aWinName = pTabWin->GetWinName(); + if(m_aTableMap.find(aWinName) != m_aTableMap.end()) + m_aTableMap.erase( aWinName ); + else + m_aTableMap.erase( pTabWin->GetComposedName() ); + + if (pTabWin == m_pLastFocusTabWin) + m_pLastFocusTabWin = NULL; + + pTabWin->clearListBox(); + delete pTabWin; + + } + if ( (sal_Int32)m_vTableConnection.size() < (nCount-1) ) // if some connections could be removed + modified(); +} +namespace +{ + // ----------------------------------------------------------------------------- + BOOL isScrollAllowed( OJoinTableView* _pView,long nDelta, BOOL bHoriz) + { + ////////////////////////////////////////////////////////////////////// + // adjust ScrollBar-Positions + ScrollBar* pBar = _pView->GetVScrollBar(); + if( bHoriz ) + pBar = _pView->GetHScrollBar(); + + long nOldThumbPos = pBar->GetThumbPos(); + long nNewThumbPos = nOldThumbPos + nDelta; + if( nNewThumbPos < 0 ) + nNewThumbPos = 0; + else if( nNewThumbPos > pBar->GetRangeMax() ) + nNewThumbPos = pBar->GetRangeMax(); + + if ( bHoriz ) + { + if( nNewThumbPos == _pView->GetScrollOffset().X() ) + return FALSE; + } + else if ( nNewThumbPos == _pView->GetScrollOffset().Y() ) + return FALSE; + + return TRUE; + } + // ----------------------------------------------------------------------------- + BOOL getMovementImpl(OJoinTableView* _pView,const Point& _rPoint,const Size& _rSize,long& _nScrollX,long& _nScrollY) + { + _nScrollY = _nScrollX = 0; + // data about the tab win + Point aUpperLeft = _rPoint; + // normalize with respect to visibility + aUpperLeft -= _pView->GetScrollOffset(); + Point aLowerRight(aUpperLeft.X() + _rSize.Width(), aUpperLeft.Y() + _rSize.Height()); + + // data about ourself + Size aSize = _pView->getRealOutputSize(); //GetOutputSizePixel(); + + BOOL bVisbile = TRUE; + BOOL bFitsHor = (aUpperLeft.X() >= 0) && (aLowerRight.X() <= aSize.Width()); + BOOL bFitsVert= (aUpperLeft.Y() >= 0) && (aLowerRight.Y() <= aSize.Height()); + if (!bFitsHor || !bFitsVert) + { + // #100386# OJ + if (!bFitsHor) + { + // ensure the visibility of the right border + if ( aLowerRight.X() > aSize.Width() ) + _nScrollX = aLowerRight.X() - aSize.Width() + TABWIN_SPACING_X; + + // ensure the visibility of the left border (higher priority) + if ( aUpperLeft.X() < 0 ) + _nScrollX = aUpperLeft.X() - TABWIN_SPACING_X; + } + + if (!bFitsVert) + { + // lower border + if ( aLowerRight.Y() > aSize.Height() ) + _nScrollY = aLowerRight.Y() - aSize.Height() + TABWIN_SPACING_Y; + // upper border + if ( aUpperLeft.Y() < 0 ) + _nScrollY = aUpperLeft.Y() - TABWIN_SPACING_Y; + } + + if ( _nScrollX ) // aSize.Width() > _rSize.Width() && + bVisbile = isScrollAllowed(_pView,_nScrollX, TRUE); + + if ( _nScrollY ) // aSize.Height() > _rSize.Height() && + bVisbile = bVisbile && isScrollAllowed(_pView,_nScrollY, FALSE); + + if ( bVisbile ) + { + sal_Int32 nHRangeMax = _pView->GetHScrollBar()->GetRangeMax(); + sal_Int32 nVRangeMax = _pView->GetVScrollBar()->GetRangeMax(); + + if ( aSize.Width() + _pView->GetHScrollBar()->GetThumbPos() + _nScrollX > nHRangeMax ) + bVisbile = FALSE; + if ( bVisbile && aSize.Height() + _pView->GetVScrollBar()->GetThumbPos() + _nScrollY > nVRangeMax ) + bVisbile = FALSE; + } + } + + + return bVisbile; + } +} // end of ano namespace +// ----------------------------------------------------------------------------- +BOOL OJoinTableView::isMovementAllowed(const Point& _rPoint,const Size& _rSize) +{ + long nX,nY; + return getMovementImpl(this,_rPoint,_rSize,nX,nY); +} +//------------------------------------------------------------------------------ +void OJoinTableView::EnsureVisible(const OTableWindow* _pWin) +{ + // data about the tab win + TTableWindowData::value_type pData = _pWin->GetData(); + EnsureVisible( pData->GetPosition() , pData->GetSize()); + Invalidate(INVALIDATE_NOCHILDREN); +} +//------------------------------------------------------------------------------ +void OJoinTableView::EnsureVisible(const Point& _rPoint,const Size& _rSize) +{ + long nScrollX,nScrollY; + + if ( getMovementImpl(this,_rPoint,_rSize,nScrollX,nScrollY) ) + { + BOOL bVisbile = TRUE; + if (nScrollX) + bVisbile = ScrollPane(nScrollX, TRUE, TRUE); + + if (nScrollY) + bVisbile = bVisbile && ScrollPane(nScrollY, FALSE, TRUE); + } +} + +//------------------------------------------------------------------------------ +void OJoinTableView::SetDefaultTabWinPosSize( OTableWindow* pTabWin ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + ////////////////////////////////////////////////////////////////// + // Position bestimmen: + // Das Fenster wird in Zeilen der Hoehe TABWIN_SPACING_Y+TABWIN_HEIGTH_STD aufgeteilt. + // Dann wird fuer jede Zeile geprueft, ob noch Platz fuer ein weiteres Fenster ist. + // Wenn kein Platz ist, wird die naechste Zeile ueberprueft. + Size aOutSize = GetSizePixel(); + Point aNewPos( 0,0 ); + USHORT nRow = 0; + BOOL bEnd = FALSE; + while( !bEnd ) + { + ////////////////////////////////////////////////////////////////// + // Neue Position auf Zeilenbeginn setzen + aNewPos.X() = TABWIN_SPACING_X; + aNewPos.Y() = (nRow+1) * TABWIN_SPACING_Y; + + ////////////////////////////////////////////////////////////////// + // Rectangle fuer die jeweilige Zeile bestimmen + Rectangle aRowRect( Point(0,0), aOutSize ); + aRowRect.Top() = nRow * ( TABWIN_SPACING_Y + TABWIN_HEIGHT_STD ); + aRowRect.Bottom() = (nRow+1) * ( TABWIN_SPACING_Y + TABWIN_HEIGHT_STD ); + + ////////////////////////////////////////////////////////////////// + // Belegte Bereiche dieser Zeile pruefen + OTableWindow* pOtherTabWin; + OTableWindowMapIterator aIter = m_aTableMap.begin(); + OTableWindowMapIterator aEnd = m_aTableMap.end(); + for(;aIter != aEnd;++aIter) + { + pOtherTabWin = aIter->second; + Rectangle aOtherTabWinRect( pOtherTabWin->GetPosPixel(), pOtherTabWin->GetSizePixel() ); + + if( + ( (aOtherTabWinRect.Top()>aRowRect.Top()) && (aOtherTabWinRect.Top()<aRowRect.Bottom()) ) || + ( (aOtherTabWinRect.Bottom()>aRowRect.Top()) && (aOtherTabWinRect.Bottom()<aRowRect.Bottom()) ) + ) + { + ////////////////////////////////////////////////////////////////// + // TabWin liegt in der Zeile + if( aOtherTabWinRect.Right()>aNewPos.X() ) + aNewPos.X() = aOtherTabWinRect.Right() + TABWIN_SPACING_X; + } + } + + ////////////////////////////////////////////////////////////////// + // Ist in dieser Zeile noch Platz? + if( (aNewPos.X()+TABWIN_WIDTH_STD)<aRowRect.Right() ) + { + aNewPos.Y() = aRowRect.Top() + TABWIN_SPACING_Y; + bEnd = TRUE; + } + else + { + if( (aRowRect.Bottom()+aRowRect.GetHeight()) > aOutSize.Height() ) + { + // insert it in the first row + sal_Int32 nCount = m_aTableMap.size() % (nRow+1); + ++nCount; + aNewPos.Y() = nCount * TABWIN_SPACING_Y + (nCount-1)*CalcZoom(TABWIN_HEIGHT_STD); + bEnd = TRUE; + } + else + nRow++; + + } + } + + ////////////////////////////////////////////////////////////////// + // Groesse bestimmen + Size aNewSize( CalcZoom(TABWIN_WIDTH_STD), CalcZoom(TABWIN_HEIGHT_STD) ); + + // check if the new position in inside the scrollbars ranges + Point aBottom(aNewPos); + aBottom.X() += aNewSize.Width(); + aBottom.Y() += aNewSize.Height(); + + if(!GetHScrollBar()->GetRange().IsInside(aBottom.X())) + GetHScrollBar()->SetRange( Range(0, aBottom.X()) ); + if(!GetVScrollBar()->GetRange().IsInside(aBottom.Y())) + GetVScrollBar()->SetRange( Range(0, aBottom.Y()) ); + + pTabWin->SetPosSizePixel( aNewPos, aNewSize ); +} + +//------------------------------------------------------------------------------ +void OJoinTableView::DataChanged(const DataChangedEvent& rDCEvt) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + if (rDCEvt.GetType() == DATACHANGED_SETTINGS) + { + // nehmen wir den worst-case an : die Farben haben sich geaendert, also + // mich anpassen + InitColors(); + Invalidate(INVALIDATE_NOCHILDREN); + // durch das Invalidate werden auch die Connections neu gezeichnet, so dass die auch + // gleich in den neuen Farben dargestellt werden + } +} + +//------------------------------------------------------------------------------ +void OJoinTableView::InitColors() +{ + DBG_CHKTHIS(OJoinTableView,NULL); + // die Farben fuer die Darstellung sollten die Systemfarben sein + StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings(); + SetBackground(Wallpaper(Color(aSystemStyle.GetDialogColor()))); +} + +//------------------------------------------------------------------------------ +void OJoinTableView::BeginChildMove( OTableWindow* pTabWin, const Point& rMousePos ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + + if (m_pView->getController().isReadOnly()) + return; + + m_pDragWin = pTabWin; + SetPointer(Pointer(POINTER_MOVE)); + Point aMousePos = ScreenToOutputPixel( rMousePos ); + m_aDragOffset = aMousePos - pTabWin->GetPosPixel(); + m_pDragWin->SetZOrder(NULL, WINDOW_ZORDER_FIRST); + m_bTrackingInitiallyMoved = FALSE; + StartTracking(); +} + +void OJoinTableView::NotifyTitleClicked( OTableWindow* pTabWin, const Point rMousePos ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + DeselectConn(GetSelectedConn()); + BeginChildMove(pTabWin, rMousePos); +} + +//------------------------------------------------------------------------------ +void OJoinTableView::BeginChildSizing( OTableWindow* pTabWin, const Pointer& rPointer ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + + if (m_pView->getController().isReadOnly()) + return; + + SetPointer( rPointer ); + m_pSizingWin = pTabWin; + StartTracking(); +} + +//------------------------------------------------------------------------------ +BOOL OJoinTableView::ScrollPane( long nDelta, BOOL bHoriz, BOOL bPaintScrollBars ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + BOOL bRet = TRUE; + + ////////////////////////////////////////////////////////////////////// + // ScrollBar-Positionen anpassen + if( bPaintScrollBars ) + { + if( bHoriz ) + { + long nOldThumbPos = GetHScrollBar()->GetThumbPos(); + long nNewThumbPos = nOldThumbPos + nDelta; + if( nNewThumbPos < 0 ) + { + nNewThumbPos = 0; + bRet = FALSE; + } + if( nNewThumbPos > GetHScrollBar()->GetRange().Max() ) + { + nNewThumbPos = GetHScrollBar()->GetRange().Max(); + bRet = FALSE; + } + GetHScrollBar()->SetThumbPos( nNewThumbPos ); + nDelta = GetHScrollBar()->GetThumbPos() - nOldThumbPos; + } + else + { + long nOldThumbPos = GetVScrollBar()->GetThumbPos(); + long nNewThumbPos = nOldThumbPos+nDelta; + if( nNewThumbPos < 0 ) + { + nNewThumbPos = 0; + bRet = FALSE; + } + if( nNewThumbPos > GetVScrollBar()->GetRange().Max() ) + { + nNewThumbPos = GetVScrollBar()->GetRange().Max(); + bRet = FALSE; + } + GetVScrollBar()->SetThumbPos( nNewThumbPos ); + nDelta = GetVScrollBar()->GetThumbPos() - nOldThumbPos; + } + } + + ////////////////////////////////////////////////////////////////////// + // Wenn ScrollOffset bereits an den Grenzen liegt, kein Neuzeichnen + if( (GetHScrollBar()->GetThumbPos()==m_aScrollOffset.X()) && + (GetVScrollBar()->GetThumbPos()==m_aScrollOffset.Y()) ) + return FALSE; + + ////////////////////////////////////////////////////////////////////// + // ScrollOffset neu setzen + if (bHoriz) + m_aScrollOffset.X() = GetHScrollBar()->GetThumbPos(); + else + m_aScrollOffset.Y() = GetVScrollBar()->GetThumbPos(); + + ////////////////////////////////////////////////////////////////////// + // Alle Fenster verschieben + OTableWindow* pTabWin; + Point aPos; + + OTableWindowMapIterator aIter = m_aTableMap.begin(); + OTableWindowMapIterator aEnd = m_aTableMap.end(); + for(;aIter != aEnd;++aIter) + { + pTabWin = aIter->second; + aPos = pTabWin->GetPosPixel(); + + if( bHoriz ) + aPos.X() -= nDelta; + else aPos.Y() -= nDelta; + + pTabWin->SetPosPixel( aPos ); + } + + Invalidate(); // INVALIDATE_NOCHILDREN + + return bRet; +} + +//------------------------------------------------------------------------------ +void OJoinTableView::Tracking( const TrackingEvent& rTEvt ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + HideTracking(); + + if (rTEvt.IsTrackingEnded()) + { + if( m_pDragWin ) + { + if (m_aDragScrollTimer.IsActive()) + m_aDragScrollTimer.Stop(); + + ////////////////////////////////////////////////////////////////////// + // Position des Childs nach Verschieben anpassen + ////////////////////////////////////////////////////////////////////// + // Fenster duerfen nicht aus Anzeigebereich herausbewegt werden + Point aDragWinPos = rTEvt.GetMouseEvent().GetPosPixel() - m_aDragOffset; + Size aDragWinSize = m_pDragWin->GetSizePixel(); + if( aDragWinPos.X() < 0 ) + aDragWinPos.X() = 0; + if( aDragWinPos.Y() < 0 ) + aDragWinPos.Y() = 0; + if( (aDragWinPos.X() + aDragWinSize.Width()) > m_aOutputSize.Width() ) + aDragWinPos.X() = m_aOutputSize.Width() - aDragWinSize.Width() - 1; + if( (aDragWinPos.Y() + aDragWinSize.Height()) > m_aOutputSize.Height() ) + aDragWinPos.Y() = m_aOutputSize.Height() - aDragWinSize.Height() - 1; + if( aDragWinPos.X() < 0 ) + aDragWinPos.X() = 0; + if( aDragWinPos.Y() < 0 ) + aDragWinPos.Y() = 0; + // TODO : nicht das Fenster neu positionieren, wenn es uebersteht, sondern einfach meinen Bereich erweitern + + + ////////////////////////////////////////////////////////////////////// + // Fenster positionieren + EndTracking(); + m_pDragWin->SetZOrder(NULL, WINDOW_ZORDER_FIRST); + // erst mal testen, ob ich mich ueberhaupt bewegt habe + // (das verhindert das Setzen des modified-Flags, wenn sich eigentlich gar nichts getan hat) + TTableWindowData::value_type pData = m_pDragWin->GetData(); + if ( ! (pData && pData->HasPosition() && (pData->GetPosition() == aDragWinPos))) + { + // die alten logischen Koordinaten + Point ptOldPos = m_pDragWin->GetPosPixel() + Point(GetHScrollBar()->GetThumbPos(), GetVScrollBar()->GetThumbPos()); + // neu positionieren + m_pDragWin->SetPosPixel(aDragWinPos); + TabWinMoved(m_pDragWin, ptOldPos); + + m_pDragWin->GrabFocus(); + } + m_pDragWin = NULL; + SetPointer(Pointer(POINTER_ARROW)); + } + // else we handle the resizing + else if( m_pSizingWin ) + { + SetPointer( Pointer() ); + EndTracking(); + + // die alten physikalischen Koordinaten + + Size szOld = m_pSizingWin->GetSizePixel(); + Point ptOld = m_pSizingWin->GetPosPixel(); + Size aNewSize(CalcZoom(m_aSizingRect.GetSize().Width()),CalcZoom(m_aSizingRect.GetSize().Height())); + m_pSizingWin->SetPosSizePixel( m_aSizingRect.TopLeft(), aNewSize ); + TabWinSized(m_pSizingWin, ptOld, szOld); + + m_pSizingWin->Invalidate( m_aSizingRect ); + m_pSizingWin = NULL; + } + } + else if (rTEvt.IsTrackingCanceled()) + { + if (m_aDragScrollTimer.IsActive()) + m_aDragScrollTimer.Stop(); + EndTracking(); + } + else + { + if( m_pDragWin ) + { + m_ptPrevDraggingPos = rTEvt.GetMouseEvent().GetPosPixel(); + // an Fenstergrenzen scrollen + ScrollWhileDragging(); + } + + if( m_pSizingWin ) + { + Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel(); + m_aSizingRect = m_pSizingWin->getSizingRect(aMousePos,m_aOutputSize); + Update(); + ShowTracking( m_aSizingRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW ); + } + } +} + +//------------------------------------------------------------------------------ +void OJoinTableView::ConnDoubleClicked( OTableConnection* /*pConnection*/ ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); +} + +//------------------------------------------------------------------------------ +void OJoinTableView::MouseButtonDown( const MouseEvent& rEvt ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + GrabFocus(); + Window::MouseButtonDown(rEvt); +} + +//------------------------------------------------------------------------------ +void OJoinTableView::MouseButtonUp( const MouseEvent& rEvt ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + Window::MouseButtonUp(rEvt); + ////////////////////////////////////////////////////////////////////// + // Wurde eine Connection ausgewaehlt? + if( !m_vTableConnection.empty() ) + { + DeselectConn(GetSelectedConn()); + + ::std::vector<OTableConnection*>::iterator aIter = m_vTableConnection.begin(); + ::std::vector<OTableConnection*>::iterator aEnd = m_vTableConnection.end(); + for(;aIter != aEnd;++aIter) + { + if( (*aIter)->CheckHit(rEvt.GetPosPixel()) ) + { + SelectConn((*aIter)); + + // Doppelclick + if( rEvt.GetClicks() == 2 ) + ConnDoubleClicked( (*aIter) ); + + break; + } + } + } +} + +//------------------------------------------------------------------------------ +void OJoinTableView::KeyInput( const KeyEvent& rEvt ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + USHORT nCode = rEvt.GetKeyCode().GetCode(); + BOOL bShift = rEvt.GetKeyCode().IsShift(); + BOOL bCtrl = rEvt.GetKeyCode().IsMod1(); + + if( !bCtrl && !bShift && (nCode==KEY_DELETE) ) + { + if (GetSelectedConn()) + RemoveConnection( GetSelectedConn() ,sal_True); + } + else + Window::KeyInput( rEvt ); +} + +//------------------------------------------------------------------------------ +void OJoinTableView::DeselectConn(OTableConnection* pConn) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + if (!pConn || !pConn->IsSelected()) + return; + + // die zugehoerigen Eitnraege in der ListBox des Tabellenfenster deselektieren + OTableWindow* pWin = pConn->GetSourceWin(); + if (pWin && pWin->GetListBox()) + pWin->GetListBox()->SelectAll(FALSE); + + pWin = pConn->GetDestWin(); + if (pWin && pWin->GetListBox()) + pWin->GetListBox()->SelectAll(FALSE); + + pConn->Deselect(); + m_pSelectedConn = NULL; +} + +//------------------------------------------------------------------------------ +void OJoinTableView::SelectConn(OTableConnection* pConn) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + DeselectConn(GetSelectedConn()); + + pConn->Select(); + m_pSelectedConn = pConn; + GrabFocus(); // has to be called here because a table window may still be focused + + // die betroffenene Eintraege in den Windows selektieren + OTableWindow* pConnSource = pConn->GetSourceWin(); + OTableWindow* pConnDest = pConn->GetDestWin(); + if (pConnSource && pConnDest) + { + OTableWindowListBox* pSourceBox = pConnSource->GetListBox(); + OTableWindowListBox* pDestBox = pConnDest->GetListBox(); + if (pSourceBox && pDestBox) + { + pSourceBox->SelectAll(FALSE); + pDestBox->SelectAll(FALSE); + + SvLBoxEntry* pFirstSourceVisible = pSourceBox->GetFirstEntryInView(); + SvLBoxEntry* pFirstDestVisible = pDestBox->GetFirstEntryInView(); + + const ::std::vector<OConnectionLine*>* pLines = pConn->GetConnLineList(); + ::std::vector<OConnectionLine*>::const_reverse_iterator aIter = pLines->rbegin(); + for(;aIter != pLines->rend();++aIter) + { + if ((*aIter)->IsValid()) + { + SvLBoxEntry* pSourceEntry = pSourceBox->GetEntryFromText((*aIter)->GetData()->GetSourceFieldName()); + if (pSourceEntry) + { + pSourceBox->Select(pSourceEntry, TRUE); + pSourceBox->MakeVisible(pSourceEntry); + } + + SvLBoxEntry* pDestEntry = pDestBox->GetEntryFromText((*aIter)->GetData()->GetDestFieldName()); + if (pDestEntry) + { + pDestBox->Select(pDestEntry, TRUE); + pDestBox->MakeVisible(pDestEntry); + } + + } + } + + if ((pFirstSourceVisible != pSourceBox->GetFirstEntryInView()) + || (pFirstDestVisible != pDestBox->GetFirstEntryInView())) + // es wurde gescrollt -> neu zeichnen + Invalidate(INVALIDATE_NOCHILDREN); + } + } +} +//------------------------------------------------------------------------------ +void OJoinTableView::Paint( const Rectangle& rRect ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + DrawConnections( rRect ); +} + +//------------------------------------------------------------------------------ +void OJoinTableView::InvalidateConnections() +{ + DBG_CHKTHIS(OJoinTableView,NULL); + ////////////////////////////////////////////////////////////////////// + // Die Joins zeichnen + ::std::for_each(m_vTableConnection.begin(),m_vTableConnection.end(), + ::std::mem_fun(& OTableConnection::InvalidateConnection)); +} + +//------------------------------------------------------------------------------ +void OJoinTableView::DrawConnections( const Rectangle& rRect ) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + ////////////////////////////////////////////////////////////////////// + // Die Joins zeichnen + ::std::for_each(m_vTableConnection.begin(),m_vTableConnection.end(),boost::bind( &OTableConnection::Draw, _1, boost::cref( rRect ))); + // zum Schluss noch mal die selektierte ueber alle anderen drueber + if (GetSelectedConn()) + GetSelectedConn()->Draw( rRect ); +} + + +//------------------------------------------------------------------------------ +::std::vector<OTableConnection*>::const_iterator OJoinTableView::getTableConnections(const OTableWindow* _pFromWin) const +{ + return ::std::find_if( m_vTableConnection.begin(), + m_vTableConnection.end(), + ::std::bind2nd(::std::mem_fun(&OTableConnection::isTableConnection),_pFromWin)); +} +// ----------------------------------------------------------------------------- +sal_Int32 OJoinTableView::getConnectionCount(const OTableWindow* _pFromWin) const +{ + return ::std::count_if( m_vTableConnection.begin(), + m_vTableConnection.end(), + ::std::bind2nd(::std::mem_fun(&OTableConnection::isTableConnection),_pFromWin)); +} +//------------------------------------------------------------------------------ +BOOL OJoinTableView::ExistsAConn(const OTableWindow* pFrom) const +{ + DBG_CHKTHIS(OJoinTableView,NULL); + return getTableConnections(pFrom) != m_vTableConnection.end(); +} +//------------------------------------------------------------------------ +void OJoinTableView::ClearAll() +{ + DBG_CHKTHIS(OJoinTableView,NULL); + SetUpdateMode(FALSE); + + HideTabWins(); + + // und das selbe mit den Connections + ::std::vector<OTableConnection*>::iterator aIter = m_vTableConnection.begin(); + ::std::vector<OTableConnection*>::iterator aEnd = m_vTableConnection.end(); + for(;aIter != aEnd;++aIter) + RemoveConnection( *aIter ,sal_True); + m_vTableConnection.clear(); + + m_pLastFocusTabWin = NULL; + m_pSelectedConn = NULL; + + // scroll to the upper left + ScrollPane(-GetScrollOffset().X(), TRUE, TRUE); + ScrollPane(-GetScrollOffset().Y(), FALSE, TRUE); + Invalidate(); +} + +//------------------------------------------------------------------------ +BOOL OJoinTableView::ScrollWhileDragging() +{ + DBG_CHKTHIS(OJoinTableView,NULL); + DBG_ASSERT(m_pDragWin != NULL, "OJoinTableView::ScrollWhileDragging darf nur waehrend Dragging eines Fensters aufgerufen werden !"); + + // den Timer schon mal killen + if (m_aDragScrollTimer.IsActive()) + m_aDragScrollTimer.Stop(); + + Point aDragWinPos = m_ptPrevDraggingPos - m_aDragOffset; + Size aDragWinSize = m_pDragWin->GetSizePixel(); + Point aLowerRight(aDragWinPos.X() + aDragWinSize.Width(), aDragWinPos.Y() + aDragWinSize.Height()); + + if (!m_bTrackingInitiallyMoved && (aDragWinPos == m_pDragWin->GetPosPixel())) + return TRUE; + + // Darstellungsfehler vermeiden (wenn bei aktivem TrackingRect gescrollt wird) + HideTracking(); + + BOOL bScrolling = FALSE; + BOOL bNeedScrollTimer = FALSE; + + // An Fenstergrenzen scrollen + // TODO : nur dann abfangen, wenn das Fenster komplett verschwinden wuerde (nicht, solange noch ein Pixel sichtbar ist) + if( aDragWinPos.X() < 5 ) + { + bScrolling = ScrollPane( -LINE_SIZE, TRUE, TRUE ); + if( !bScrolling && (aDragWinPos.X()<0) ) + aDragWinPos.X() = 0; + + // brauche ich weiteres (timergesteuertes) Scrolling ? + bNeedScrollTimer = bScrolling && (aDragWinPos.X() < 5); + } + + if( aLowerRight.X() > m_aOutputSize.Width() - 5 ) + { + bScrolling = ScrollPane( LINE_SIZE, TRUE, TRUE ) ; + if( !bScrolling && ( aLowerRight.X() > m_aOutputSize.Width() ) ) + aDragWinPos.X() = m_aOutputSize.Width() - aDragWinSize.Width(); + + // brauche ich weiteres (timergesteuertes) Scrolling ? + bNeedScrollTimer = bScrolling && (aLowerRight.X() > m_aOutputSize.Width() - 5); + } + + if( aDragWinPos.Y() < 5 ) + { + bScrolling = ScrollPane( -LINE_SIZE, FALSE, TRUE ); + if( !bScrolling && (aDragWinPos.Y()<0) ) + aDragWinPos.Y() = 0; + + bNeedScrollTimer = bScrolling && (aDragWinPos.Y() < 5); + } + + if( aLowerRight.Y() > m_aOutputSize.Height() - 5 ) + { + bScrolling = ScrollPane( LINE_SIZE, FALSE, TRUE ); + if( !bScrolling && ( (aDragWinPos.Y() + aDragWinSize.Height()) > m_aOutputSize.Height() ) ) + aDragWinPos.Y() = m_aOutputSize.Height() - aDragWinSize.Height(); + + bNeedScrollTimer = bScrolling && (aLowerRight.Y() > m_aOutputSize.Height() - 5); + } + + // Timer neu setzen, wenn noch notwendig + if (bNeedScrollTimer) + { + m_aDragScrollTimer.SetTimeout(100); + m_aDragScrollTimer.Start(); + } + + // das DraggingRect neu zeichnen + m_aDragRect = Rectangle(m_ptPrevDraggingPos - m_aDragOffset, m_pDragWin->GetSizePixel()); + Update(); + ShowTracking( m_aDragRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW ); + + return bScrolling; +} + +//------------------------------------------------------------------------ +IMPL_LINK(OJoinTableView, OnDragScrollTimer, void*, EMPTYARG) +{ + ScrollWhileDragging(); + return 0L; +} +// ----------------------------------------------------------------------------- +void OJoinTableView::invalidateAndModify(SfxUndoAction *_pAction) +{ + Invalidate(INVALIDATE_NOCHILDREN); + m_pView->getController().addUndoActionAndInvalidate(_pAction); +} +//------------------------------------------------------------------------ +void OJoinTableView::TabWinMoved(OTableWindow* ptWhich, const Point& ptOldPosition) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + Point ptThumbPos(GetHScrollBar()->GetThumbPos(), GetVScrollBar()->GetThumbPos()); + ptWhich->GetData()->SetPosition(ptWhich->GetPosPixel() + ptThumbPos); + + invalidateAndModify(new OJoinMoveTabWinUndoAct(this, ptOldPosition, ptWhich)); +} + +//------------------------------------------------------------------------ +void OJoinTableView::TabWinSized(OTableWindow* ptWhich, const Point& ptOldPosition, const Size& szOldSize) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + ptWhich->GetData()->SetSize(ptWhich->GetSizePixel()); + ptWhich->GetData()->SetPosition(ptWhich->GetPosPixel()); + + invalidateAndModify(new OJoinSizeTabWinUndoAct(this, ptOldPosition, szOldSize, ptWhich)); +} + +//------------------------------------------------------------------------------ +BOOL OJoinTableView::IsAddAllowed() +{ + DBG_CHKTHIS(OJoinTableView,NULL); + + // nicht wenn Db readonly + if (m_pView->getController().isReadOnly()) + return FALSE; + + try + { + Reference< XConnection> xConnection = m_pView->getController().getConnection(); + if(!xConnection.is()) + return FALSE; + // nicht wenn schon zuviele Tabellen + Reference < XDatabaseMetaData > xMetaData( xConnection->getMetaData() ); + + sal_Int32 nMax = xMetaData.is() ? xMetaData->getMaxTablesInSelect() : 0; + if (nMax && nMax <= (sal_Int32)m_aTableMap.size()) + return FALSE; + } + catch(SQLException&) + { + return FALSE; + } + + return TRUE; +} +// ----------------------------------------------------------------------------- +void OJoinTableView::executePopup(const Point& _aPos,OTableConnection* _pSelConnection) +{ + PopupMenu aContextMenu( ModuleRes( RID_MENU_JOINVIEW_CONNECTION ) ); + switch (aContextMenu.Execute(this, _aPos)) + { + case SID_DELETE: + RemoveConnection( _pSelConnection ,sal_True); + break; + case ID_QUERY_EDIT_JOINCONNECTION: + ConnDoubleClicked( _pSelConnection ); // is the same as double clicked + break; + } +} +//------------------------------------------------------------------------------ +void OJoinTableView::Command(const CommandEvent& rEvt) +{ + DBG_CHKTHIS(OJoinTableView,NULL); + + BOOL bHandled = FALSE; + + switch (rEvt.GetCommand()) + { + case COMMAND_CONTEXTMENU: + { + if( m_vTableConnection.empty() ) + return; + + OTableConnection* pSelConnection = GetSelectedConn(); + // when it wasn't a mouse event use the selected connection + if (!rEvt.IsMouseEvent()) + { + if( pSelConnection ) + { + const ::std::vector<OConnectionLine*>* pLines = pSelConnection->GetConnLineList(); + ::std::vector<OConnectionLine*>::const_iterator aIter = ::std::find_if(pLines->begin(),pLines->end(),::std::mem_fun(&OConnectionLine::IsValid)); + if( aIter != pLines->end() ) + executePopup((*aIter)->getMidPoint(),pSelConnection); + } + } + else + { + DeselectConn(pSelConnection); + + const Point& aMousePos = rEvt.GetMousePosPixel(); + ::std::vector<OTableConnection*>::iterator aIter = m_vTableConnection.begin(); + ::std::vector<OTableConnection*>::iterator aEnd = m_vTableConnection.end(); + for(;aIter != aEnd;++aIter) + { + if( (*aIter)->CheckHit(aMousePos) ) + { + SelectConn(*aIter); + if(!getDesignView()->getController().isReadOnly() && getDesignView()->getController().isConnected()) + executePopup(rEvt.GetMousePosPixel(),*aIter); + break; + } + } + } + bHandled = TRUE; + } + } + if (!bHandled) + Window::Command(rEvt); +} + +//------------------------------------------------------------------------------ +OTableConnection* OJoinTableView::GetTabConn(const OTableWindow* pLhs,const OTableWindow* pRhs,bool _bSupressCrossOrNaturalJoin,const OTableConnection* _rpFirstAfter) const +{ + OTableConnection* pConn = NULL; + DBG_ASSERT(pRhs || pLhs, "OJoinTableView::GetTabConn : invalid args !"); + // only one NULL-arg allowed + + if ((!pLhs || pLhs->ExistsAConn()) && (!pRhs || pRhs->ExistsAConn())) + { + BOOL bFoundStart = _rpFirstAfter ? FALSE : TRUE; + + ::std::vector<OTableConnection*>::const_iterator aIter = m_vTableConnection.begin(); + ::std::vector<OTableConnection*>::const_iterator aEnd = m_vTableConnection.end(); + for(;aIter != aEnd;++aIter) + { + OTableConnection* pData = *aIter; + + if ( ( (pData->GetSourceWin() == pLhs) + && ( (pData->GetDestWin() == pRhs) + || (NULL == pRhs) + ) + ) + || ( (pData->GetSourceWin() == pRhs) + && ( (pData->GetDestWin() == pLhs) + || (NULL == pLhs) + ) + ) + ) + { + if ( _bSupressCrossOrNaturalJoin ) + { + if ( supressCrossNaturalJoin(pData->GetData()) ) + continue; + } + if (bFoundStart) + { + pConn = pData; + break; + } + + if (!pConn) + // used as fallback : if there is no conn after _rpFirstAfter the first conn between the two tables + // will be used + pConn = pData; + + if (pData == _rpFirstAfter) + bFoundStart = TRUE; + } + } + } + return pConn; +} + +//------------------------------------------------------------------------------ +long OJoinTableView::PreNotify(NotifyEvent& rNEvt) +{ + BOOL bHandled = FALSE; + switch (rNEvt.GetType()) + { + case EVENT_COMMAND: + { + const CommandEvent* pCommand = rNEvt.GetCommandEvent(); + if (pCommand->GetCommand() == COMMAND_WHEEL) + { + const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData(); + if (pData->GetMode() == COMMAND_WHEEL_SCROLL) + { + if (pData->GetDelta() > 0) + ScrollPane(-10 * pData->GetScrollLines(), pData->IsHorz(), TRUE); + else + ScrollPane(10 * pData->GetScrollLines(), pData->IsHorz(), TRUE); + bHandled = TRUE; + } + } + } + break; + case EVENT_KEYINPUT: + { + if (m_aTableMap.empty()) + // no tab wins -> no conns -> no traveling + break; + + const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent(); + if (!pKeyEvent->GetKeyCode().IsMod1()) + { + switch (pKeyEvent->GetKeyCode().GetCode()) + { + case KEY_TAB: + { + if (!HasChildPathFocus()) + break; + + BOOL bForward = !pKeyEvent->GetKeyCode().IsShift(); + // is there an active tab win ? + OTableWindowMapIterator aIter = m_aTableMap.begin(); + OTableWindowMapIterator aEnd = m_aTableMap.end(); + for(;aIter != aEnd;++aIter) + if (aIter->second && aIter->second->HasChildPathFocus()) + break; + + OTableWindow* pNextWin = NULL; + OTableConnection* pNextConn = NULL; + + if (aIter != m_aTableMap.end()) + { // there is a currently active tab win + // check if there is an "overflow" and we should select a conn instead of a win + if (!m_vTableConnection.empty()) + { + if ((aIter->second == m_aTableMap.rbegin()->second) && bForward) + // the last win is active and we're travelling forward -> select the first conn + pNextConn = *m_vTableConnection.begin(); + if ((aIter == m_aTableMap.begin()) && !bForward) + // the first win is active an we're traveling backward -> select the last conn + pNextConn = *m_vTableConnection.rbegin(); + } + + if (!pNextConn) + { + // no conn for any reason -> select the next or previous tab win + if(bForward) + { + if ((aIter->second == m_aTableMap.rbegin()->second)) + pNextWin = m_aTableMap.begin()->second; + else + { + ++aIter; + pNextWin = aIter->second; + } + } + else + { + if (aIter == m_aTableMap.begin()) + pNextWin = m_aTableMap.rbegin()->second; + else + { + --aIter; + pNextWin = aIter->second; + } + } + } + } + else + { // no active tab win -> travel the connections + // find the currently selected conn within the conn list + sal_Int32 i(0); + for ( ::std::vector<OTableConnection*>::iterator connectionIter = m_vTableConnection.begin(); + connectionIter != m_vTableConnection.end(); + ++connectionIter, ++i + ) + { + if ( (*connectionIter) == GetSelectedConn() ) + break; + } + if (i == sal_Int32(m_vTableConnection.size() - 1) && bForward) + // the last conn is active and we're travelling forward -> select the first win + pNextWin = m_aTableMap.begin()->second; + if ((i == 0) && !bForward && !m_aTableMap.empty()) + // the first conn is active and we're travelling backward -> select the last win + pNextWin = m_aTableMap.rbegin()->second; + + if (pNextWin) + DeselectConn(GetSelectedConn()); + else + // no win for any reason -> select the next or previous conn + if (i < (sal_Int32)m_vTableConnection.size()) + // there is a currently active conn + pNextConn = m_vTableConnection[(i + (bForward ? 1 : m_vTableConnection.size() - 1)) % m_vTableConnection.size()]; + else + { // no tab win selected, no conn selected + if (!m_vTableConnection.empty()) + pNextConn = m_vTableConnection[bForward ? 0 : m_vTableConnection.size() - 1]; + else if (!m_aTableMap.empty()) + { + if(bForward) + pNextWin = m_aTableMap.begin()->second; + else + pNextWin = m_aTableMap.rbegin()->second; + } + } + } + + // now select the object + if (pNextWin) + { + if (pNextWin->GetListBox()) + pNextWin->GetListBox()->GrabFocus(); + else + pNextWin->GrabFocus(); + EnsureVisible(pNextWin); + } + else if (pNextConn) + { + GrabFocus(); + // neccessary : a conn may be selected even if a tab win has the focus, in this case + // the next travel would select the same conn again if we would not reset te focus ... + SelectConn(pNextConn); + } + } + break; + case KEY_RETURN: + { + if (!pKeyEvent->GetKeyCode().IsShift() && GetSelectedConn() && HasFocus()) + ConnDoubleClicked(GetSelectedConn()); + break; + } + } + } + } + break; + case EVENT_GETFOCUS: + { + if (m_aTableMap.empty()) + // no tab wins -> no conns -> no focus change + break; + Window* pSource = rNEvt.GetWindow(); + if (pSource) + { + Window* pSearchFor = NULL; + if (pSource->GetParent() == this) + // it may be one of the tab wins + pSearchFor = pSource; + else if (pSource->GetParent() && (pSource->GetParent()->GetParent() == this)) + // it may be one of th list boxes of one of the tab wins + pSearchFor = pSource->GetParent(); + + if (pSearchFor) + { + OTableWindowMapIterator aIter = m_aTableMap.begin(); + OTableWindowMapIterator aEnd = m_aTableMap.end(); + for(;aIter != aEnd;++aIter) + { + if (aIter->second == pSearchFor) + { + m_pLastFocusTabWin = aIter->second; + break; + } + } + } + } + } + break; + } + + if (!bHandled) + return Window::PreNotify(rNEvt); + return 1L; +} + +//------------------------------------------------------------------------------ +void OJoinTableView::GrabTabWinFocus() +{ + if (m_pLastFocusTabWin && m_pLastFocusTabWin->IsVisible()) + { + if (m_pLastFocusTabWin->GetListBox()) + m_pLastFocusTabWin->GetListBox()->GrabFocus(); + else + m_pLastFocusTabWin->GrabFocus(); + } + else if (!m_aTableMap.empty() && m_aTableMap.begin()->second && m_aTableMap.begin()->second->IsVisible()) + { + OTableWindow* pFirstWin = m_aTableMap.begin()->second; + if (pFirstWin->GetListBox()) + pFirstWin->GetListBox()->GrabFocus(); + else + pFirstWin->GrabFocus(); + } +} +// ----------------------------------------------------------------------------- +void OJoinTableView::StateChanged( StateChangedType nType ) +{ + Window::StateChanged( nType ); + + if ( nType == STATE_CHANGE_ZOOM ) + { + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + Font aFont = rStyleSettings.GetGroupFont(); + if ( IsControlFont() ) + aFont.Merge( GetControlFont() ); + SetZoomedPointFont( aFont ); + + OTableWindowMapIterator aIter = m_aTableMap.begin(); + OTableWindowMapIterator aEnd = m_aTableMap.end(); + for(;aIter != aEnd;++aIter) + { + aIter->second->SetZoom(GetZoom()); + Size aSize(CalcZoom(aIter->second->GetSizePixel().Width()),CalcZoom(aIter->second->GetSizePixel().Height())); + aIter->second->SetSizePixel(aSize); + } + Resize(); + } +} +//------------------------------------------------------------------------------ +void OJoinTableView::HideTabWins() +{ + DBG_CHKTHIS(OJoinTableView,NULL); + SetUpdateMode(sal_False); + + OTableWindowMap* pTabWins = GetTabWinMap(); + if ( pTabWins ) + { + // working on a copy because the real list will be cleared in inner calls + OTableWindowMap aCopy(*pTabWins); + OTableWindowMap::iterator aIter = aCopy.begin(); + OTableWindowMap::iterator aEnd = aCopy.end(); + for(;aIter != aEnd;++aIter) + RemoveTabWin(aIter->second); + } + + m_pView->getController().setModified(sal_True); + + SetUpdateMode(sal_True); + +} +// ----------------------------------------------------------------------------- +sal_Int8 OJoinTableView::AcceptDrop( const AcceptDropEvent& /*_rEvt*/ ) +{ + return DND_ACTION_NONE; +} +// ----------------------------------------------------------------------------- +sal_Int8 OJoinTableView::ExecuteDrop( const ExecuteDropEvent& /*_rEvt*/ ) +{ + return DND_ACTION_NONE; +} +// ----------------------------------------------------------------------------- +void OJoinTableView::dragFinished( ) +{ +} +//------------------------------------------------------------------------------ +void OJoinTableView::StartDrag( sal_Int8 /*nAction*/, const Point& /*rPosPixel*/ ) +{ +} +// ----------------------------------------------------------------------------- +void OJoinTableView::clearLayoutInformation() +{ + m_pLastFocusTabWin = NULL; + m_pSelectedConn = NULL; + ////////////////////////////////////////////////////////////////////// + // Listen loeschen + OTableWindowMapIterator aIter = m_aTableMap.begin(); + OTableWindowMapIterator aEnd = m_aTableMap.end(); + for(;aIter != aEnd;++aIter) + { + if ( aIter->second ) + aIter->second->clearListBox(); + ::std::auto_ptr<Window> aTemp(aIter->second); + aIter->second = NULL; + } + + m_aTableMap.clear(); + + ::std::vector<OTableConnection*>::const_iterator aIter2 = m_vTableConnection.begin(); + ::std::vector<OTableConnection*>::const_iterator aEnd2 = m_vTableConnection.end(); + for(;aIter2 != aEnd2;++aIter2) + delete *aIter2; + + m_vTableConnection.clear(); +} +// ----------------------------------------------------------------------------- +void OJoinTableView::lookForUiActivities() +{ +} +// ----------------------------------------------------------------------------- +void OJoinTableView::LoseFocus() +{ + DeselectConn(GetSelectedConn()); + Window::LoseFocus(); +} +// ----------------------------------------------------------------------------- +void OJoinTableView::GetFocus() +{ + Window::GetFocus(); + if ( !m_aTableMap.empty() && !GetSelectedConn() ) + GrabTabWinFocus(); +} +// ----------------------------------------------------------------------------- +Reference< XAccessible > OJoinTableView::CreateAccessible() +{ + m_pAccessible = new OJoinDesignViewAccess(this); + return m_pAccessible; +} +// ----------------------------------------------------------------------------- +void OJoinTableView::modified() +{ + OJoinController& rController = m_pView->getController(); + rController.setModified( sal_True ); + rController.InvalidateFeature(ID_BROWSER_ADDTABLE); + rController.InvalidateFeature(SID_RELATION_ADD_RELATION); +} +// ----------------------------------------------------------------------------- +void OJoinTableView::addConnection(OTableConnection* _pConnection,sal_Bool _bAddData) +{ + if ( _bAddData ) + { +#if OSL_DEBUG_LEVEL > 0 + TTableConnectionData* pTabConnDataList = m_pView->getController().getTableConnectionData(); + OSL_ENSURE( ::std::find(pTabConnDataList->begin(),pTabConnDataList->end(),_pConnection->GetData()) == pTabConnDataList->end(),"Data already in vector!"); +#endif + m_pView->getController().getTableConnectionData()->push_back(_pConnection->GetData()); + } + m_vTableConnection.push_back(_pConnection); + _pConnection->RecalcLines(); + _pConnection->InvalidateConnection(); + + modified(); + if ( m_pAccessible ) + m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD, + Any(), + makeAny(_pConnection->GetAccessible())); +} +// ----------------------------------------------------------------------------- +bool OJoinTableView::allowQueries() const +{ + return true; +} +// ----------------------------------------------------------------------------- +void OJoinTableView::onNoColumns_throw() +{ + OSL_ENSURE( false, "OTableWindow::onNoColumns_throw: cannot really handle this!" ); + throw SQLException(); +} +//------------------------------------------------------------------------------ +bool OJoinTableView::supressCrossNaturalJoin(const TTableConnectionData::value_type& ) const +{ + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QTableConnection.cxx b/dbaccess/source/ui/querydesign/QTableConnection.cxx new file mode 100644 index 000000000000..98a21fbb21ea --- /dev/null +++ b/dbaccess/source/ui/querydesign/QTableConnection.cxx @@ -0,0 +1,99 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "QTableConnection.hxx" +#include <tools/debug.hxx> +#include "QueryTableView.hxx" +#include "ConnectionLine.hxx" +using namespace dbaui; +//======================================================================== +// class OQueryTableConnection +//======================================================================== +DBG_NAME(OQueryTableConnection) + +//------------------------------------------------------------------------ +OQueryTableConnection::OQueryTableConnection(OQueryTableView* pContainer, const TTableConnectionData::value_type& pTabConnData) + :OTableConnection(pContainer, pTabConnData) + ,m_bVisited(sal_False) +{ + DBG_CTOR(OQueryTableConnection,NULL); +} + +//------------------------------------------------------------------------ +OQueryTableConnection::OQueryTableConnection(const OQueryTableConnection& rConn) + :OTableConnection( rConn ) +{ + DBG_CTOR(OQueryTableConnection,NULL); + // keine eigenen Members, also reicht die Basisklassenfunktionalitaet +} +//------------------------------------------------------------------------ +OQueryTableConnection::~OQueryTableConnection() +{ + DBG_DTOR(OQueryTableConnection,NULL); +} + +//------------------------------------------------------------------------ +OQueryTableConnection& OQueryTableConnection::operator=(const OQueryTableConnection& rConn) +{ + if (&rConn == this) + return *this; + + OTableConnection::operator=(rConn); + // keine eigenen Members ... + return *this; +} + +//------------------------------------------------------------------------ +sal_Bool OQueryTableConnection::operator==(const OQueryTableConnection& rCompare) +{ + DBG_ASSERT(GetData() && rCompare.GetData(), "OQueryTableConnection::operator== : einer der beiden Teilnehmer hat keine Daten !"); + + // allzuviel brauche ich nicht vergleichen (schon gar nicht alle Member) : lediglich die Fenster, an denen wir haengen, und + // die Indizies in der entsprechenden Tabelle muessen uebereinstimmen + OQueryTableConnectionData* pMyData = static_cast<OQueryTableConnectionData*>(GetData().get()); + OQueryTableConnectionData* pCompData = static_cast<OQueryTableConnectionData*>(rCompare.GetData().get()); + + // Connections werden als gleich angesehen, wenn sie in Source-/Dest-Fenstername und Source-/Dest-FieldIndex uebereinstimmen ... + return ( ( (pMyData->getReferencedTable() == pCompData->getReferencedTable()) && + (pMyData->getReferencingTable() == pCompData->getReferencingTable()) && + (pMyData->GetFieldIndex(JTCS_TO) == pCompData->GetFieldIndex(JTCS_TO)) && + (pMyData->GetFieldIndex(JTCS_FROM) == pCompData->GetFieldIndex(JTCS_FROM)) + ) + || // ... oder diese Uebereinstimmung ueber Kreuz besteht + ( (pMyData->getReferencingTable() == pCompData->getReferencedTable()) && + (pMyData->getReferencedTable() == pCompData->getReferencingTable()) && + (pMyData->GetFieldIndex(JTCS_TO) == pCompData->GetFieldIndex(JTCS_FROM)) && + (pMyData->GetFieldIndex(JTCS_FROM) == pCompData->GetFieldIndex(JTCS_TO)) + ) + ); +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QTableConnection.hxx b/dbaccess/source/ui/querydesign/QTableConnection.hxx new file mode 100644 index 000000000000..a2402acab43b --- /dev/null +++ b/dbaccess/source/ui/querydesign/QTableConnection.hxx @@ -0,0 +1,59 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QUERYTABLECONNECTION_HXX +#define DBAUI_QUERYTABLECONNECTION_HXX + +#include "TableConnection.hxx" +#include "QTableConnectionData.hxx" +#include "QEnumTypes.hxx" + +namespace dbaui +{ + //================================================================== + class OQueryTableView; + class OQueryTableConnection : public OTableConnection + { + sal_Bool m_bVisited; // is true if the conn was already visited through the join algorithm + public: + OQueryTableConnection(OQueryTableView* pContainer, const TTableConnectionData::value_type& pTabConnData); + OQueryTableConnection(const OQueryTableConnection& rConn); + virtual ~OQueryTableConnection(); + + OQueryTableConnection& operator=(const OQueryTableConnection& rConn); + sal_Bool operator==(const OQueryTableConnection& rCompare); + + inline ::rtl::OUString GetAliasName(EConnectionSide nWhich) const { return static_cast<OQueryTableConnectionData*>(GetData().get())->GetAliasName(nWhich); } + + inline sal_Bool IsVisited() const { return m_bVisited; } + inline void SetVisited(sal_Bool bVisited) { m_bVisited = bVisited; } + + }; +} +#endif // DBAUI_QUERYTABLECONNECTION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QTableConnectionData.cxx b/dbaccess/source/ui/querydesign/QTableConnectionData.cxx new file mode 100644 index 000000000000..991ef5733171 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QTableConnectionData.cxx @@ -0,0 +1,169 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "QTableConnectionData.hxx" +#include <tools/debug.hxx> +#include "QTableConnectionData.hxx" +#include "QTableWindow.hxx" + +using namespace dbaui; + +//======================================================================== +// class OQueryTableConnectionData +//======================================================================== +DBG_NAME(OQueryTableConnectionData) +//------------------------------------------------------------------------ +OQueryTableConnectionData::OQueryTableConnectionData() + :OTableConnectionData() + ,m_eJoinType (INNER_JOIN) + ,m_bNatural(false) +{ + DBG_CTOR(OQueryTableConnectionData,NULL); +} + +//------------------------------------------------------------------------ +OQueryTableConnectionData::OQueryTableConnectionData( const OQueryTableConnectionData& rConnData ) + :OTableConnectionData( rConnData ) +{ + DBG_CTOR(OQueryTableConnectionData,NULL); + m_nFromEntryIndex = rConnData.m_nFromEntryIndex; + m_nDestEntryIndex = rConnData.m_nDestEntryIndex; + + m_eFromType = rConnData.m_eFromType; + m_eDestType = rConnData.m_eDestType; + m_eJoinType = rConnData.m_eJoinType; + m_bNatural = rConnData.m_bNatural; +} + +//------------------------------------------------------------------------ +OQueryTableConnectionData::OQueryTableConnectionData(const TTableWindowData::value_type& _pReferencingTable + ,const TTableWindowData::value_type& _pReferencedTable + ,const ::rtl::OUString& rConnName) + :OTableConnectionData( _pReferencingTable,_pReferencedTable, rConnName ) + ,m_nFromEntryIndex(0) + ,m_nDestEntryIndex(0) + ,m_eJoinType (INNER_JOIN) + ,m_bNatural(false) + ,m_eFromType(TAB_NORMAL_FIELD) + ,m_eDestType(TAB_NORMAL_FIELD) +{ + DBG_CTOR(OQueryTableConnectionData,NULL); +} + +//------------------------------------------------------------------------ +OQueryTableConnectionData::~OQueryTableConnectionData() +{ + DBG_DTOR(OQueryTableConnectionData,NULL); +} + +//------------------------------------------------------------------------ +OConnectionLineDataRef OQueryTableConnectionData::CreateLineDataObj() +{ + DBG_CHKTHIS(OQueryTableConnectionData,NULL); + // keine Spezialisierung bei den LineDatas, also eine Instanz der Standard-Klasse + return new OConnectionLineData(); +} + +//------------------------------------------------------------------------ +OConnectionLineDataRef OQueryTableConnectionData::CreateLineDataObj( const OConnectionLineData& rConnLineData ) +{ + DBG_CHKTHIS(OQueryTableConnectionData,NULL); + return new OConnectionLineData( rConnLineData ); +} + +//------------------------------------------------------------------------ +void OQueryTableConnectionData::CopyFrom(const OTableConnectionData& rSource) +{ + DBG_CHKTHIS(OQueryTableConnectionData,NULL); + // wie in der Basisklasse zurueckziehen auf das (nicht-virtuelle) operator= + *this = (const OQueryTableConnectionData&)rSource; +} + +//------------------------------------------------------------------------ +OQueryTableConnectionData& OQueryTableConnectionData::operator=(const OQueryTableConnectionData& rConnData) +{ + DBG_CHKTHIS(OQueryTableConnectionData,NULL); + if (&rConnData == this) + return *this; + + OTableConnectionData::operator=(rConnData); + + m_nFromEntryIndex = rConnData.m_nFromEntryIndex; + m_nDestEntryIndex = rConnData.m_nDestEntryIndex; + + m_eFromType = rConnData.m_eFromType; + m_eDestType = rConnData.m_eDestType; + m_eJoinType = rConnData.m_eJoinType; + m_bNatural = rConnData.m_bNatural; + + return *this; +} + +//------------------------------------------------------------------------------ +::rtl::OUString OQueryTableConnectionData::GetAliasName(EConnectionSide nWhich) const +{ + DBG_CHKTHIS(OQueryTableConnectionData,NULL); + return nWhich == JTCS_FROM ? m_pReferencingTable->GetWinName() : m_pReferencedTable->GetWinName(); +} + +//------------------------------------------------------------------------------ +void OQueryTableConnectionData::InitFromDrag(const OTableFieldDescRef& rDragLeft, const OTableFieldDescRef& rDragRight) +{ + DBG_CHKTHIS(OQueryTableConnectionData,NULL); + // die Infos in rDrag in Parameter fuer das Basisklassen-Init umsetzen ... + OQueryTableWindow* pSourceWin = static_cast<OQueryTableWindow*>(rDragLeft->GetTabWindow()); + OQueryTableWindow* pDestWin = static_cast<OQueryTableWindow*>(rDragRight->GetTabWindow()); + OSL_ENSURE(pSourceWin,"NO Source window found!"); + OSL_ENSURE(pDestWin,"NO Dest window found!"); + m_pReferencingTable = pSourceWin->GetData(); + m_pReferencedTable = pDestWin->GetData(); + + // und dann meine Members setzen + SetFieldIndex(JTCS_FROM, rDragLeft->GetFieldIndex()); + SetFieldIndex(JTCS_TO, rDragRight->GetFieldIndex()); + + SetFieldType(JTCS_FROM, rDragLeft->GetFieldType()); + SetFieldType(JTCS_TO, rDragRight->GetFieldType()); + + AppendConnLine((::rtl::OUString)rDragLeft->GetField(),(::rtl::OUString)rDragRight->GetField()); +} +// ----------------------------------------------------------------------------- +OTableConnectionData* OQueryTableConnectionData::NewInstance() const +{ + return new OQueryTableConnectionData(); +} +// ----------------------------------------------------------------------------- +BOOL OQueryTableConnectionData::Update() +{ + return TRUE; +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QTableConnectionData.hxx b/dbaccess/source/ui/querydesign/QTableConnectionData.hxx new file mode 100644 index 000000000000..f7d2173907b1 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QTableConnectionData.hxx @@ -0,0 +1,91 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QTABLECONNECTIONDATA_HXX +#define DBAUI_QTABLECONNECTIONDATA_HXX + +#include "TableConnectionData.hxx" +#include "TableFieldDescription.hxx" +#include "QEnumTypes.hxx" +#include <tools/rtti.hxx> + +namespace dbaui +{ + class OQueryTableConnectionData : public OTableConnectionData + { + sal_Int32 m_nFromEntryIndex; + sal_Int32 m_nDestEntryIndex; + EJoinType m_eJoinType; + bool m_bNatural; + + ETableFieldType m_eFromType; + ETableFieldType m_eDestType; + + protected: + // fuer das Anlegen und Duplizieren von Lines vom eigenen Typ + virtual OConnectionLineDataRef CreateLineDataObj(); + virtual OConnectionLineDataRef CreateLineDataObj( const OConnectionLineData& rConnLineData ); + + OQueryTableConnectionData& operator=( const OQueryTableConnectionData& rConnData ); + public: + OQueryTableConnectionData(); + OQueryTableConnectionData( const OQueryTableConnectionData& rConnData ); + OQueryTableConnectionData( const TTableWindowData::value_type& _pReferencingTable,const TTableWindowData::value_type& _pReferencedTable, + const ::rtl::OUString& rConnName=::rtl::OUString()); + virtual ~OQueryTableConnectionData(); + + virtual void CopyFrom(const OTableConnectionData& rSource); + virtual OTableConnectionData* NewInstance() const; + + + /** Update create a new connection + + @return true if successful + */ + virtual BOOL Update(); + + ::rtl::OUString GetAliasName(EConnectionSide nWhich) const; + + sal_Int32 GetFieldIndex(EConnectionSide nWhich) const { return nWhich==JTCS_TO ? m_nDestEntryIndex : m_nFromEntryIndex; } + void SetFieldIndex(EConnectionSide nWhich, sal_Int32 nVal) { if (nWhich==JTCS_TO) m_nDestEntryIndex=nVal; else m_nFromEntryIndex=nVal; } + + ETableFieldType GetFieldType(EConnectionSide nWhich) const { return nWhich==JTCS_TO ? m_eDestType : m_eFromType; } + void SetFieldType(EConnectionSide nWhich, ETableFieldType eType) { if (nWhich==JTCS_TO) m_eDestType=eType; else m_eFromType=eType; } + + void InitFromDrag(const OTableFieldDescRef& rDragLeft, const OTableFieldDescRef& rDragRight); + + EJoinType GetJoinType() const { return m_eJoinType; }; + void SetJoinType(const EJoinType& eJT) { m_eJoinType = eJT; }; + + inline void setNatural(bool _bNatural) { m_bNatural = _bNatural; } + inline bool isNatural() const { return m_bNatural; } + }; + +} +#endif // DBAUI_QTABLECONNECTIONDATA_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QTableWindow.cxx b/dbaccess/source/ui/querydesign/QTableWindow.cxx new file mode 100644 index 000000000000..60fc544a276f --- /dev/null +++ b/dbaccess/source/ui/querydesign/QTableWindow.cxx @@ -0,0 +1,241 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "QTableWindow.hxx" +#include "QueryTableView.hxx" +#include "dbustrings.hrc" +#include <tools/debug.hxx> +#include "dbaccess_helpid.hrc" +#include "QueryDesignView.hxx" +#include "browserids.hxx" +#include "querycontroller.hxx" +#include <vcl/image.hxx> +#include "TableWindowListBox.hxx" +#include "dbu_qry.hrc" +#include "Query.hrc" +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include "TableFieldInfo.hxx" +#include <comphelper/uno3.hxx> +#include <comphelper/extract.hxx> +#include "UITools.hxx" + + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::beans; +using namespace dbaui; +//======================================================================== +// class OQueryTableWindow +//======================================================================== +DBG_NAME(OQueryTableWindow) +//------------------------------------------------------------------------------ +OQueryTableWindow::OQueryTableWindow( Window* pParent, const TTableWindowData::value_type& pTabWinData, sal_Unicode* pszInitialAlias) + :OTableWindow( pParent, pTabWinData ) + ,m_nAliasNum(0) +{ + DBG_CTOR(OQueryTableWindow,NULL); + if (pszInitialAlias != NULL) + m_strInitialAlias = ::rtl::OUString(pszInitialAlias); + else + m_strInitialAlias = GetAliasName(); + + // wenn der Tabellen- gleich dem Aliasnamen ist, dann darf ich das nicht an InitialAlias weiterreichen, denn das Anhaengen + // eines eventuelle Tokens nicht klappen ... + if (m_strInitialAlias == pTabWinData->GetTableName()) + m_strInitialAlias = ::rtl::OUString(); + + SetHelpId(HID_CTL_QRYDGNTAB); +} + +//------------------------------------------------------------------------------ +OQueryTableWindow::~OQueryTableWindow() +{ + DBG_DTOR(OQueryTableWindow,NULL); +} + +//------------------------------------------------------------------------------ +sal_Bool OQueryTableWindow::Init() +{ + sal_Bool bSuccess = OTableWindow::Init(); + if(!bSuccess) + return bSuccess; + + OQueryTableView* pContainer = static_cast<OQueryTableView*>(getTableView()); + + // zuerst Alias bestimmen + ::rtl::OUString sAliasName; + + TTableWindowData::value_type pWinData = GetData(); + + if (m_strInitialAlias.getLength() ) + // Der Alias wurde explizit mit angegeben + sAliasName = m_strInitialAlias; + else if ( GetTable().is() ) + GetTable()->getPropertyValue( PROPERTY_NAME ) >>= sAliasName; + else + return sal_False; + + // Alias mit fortlaufender Nummer versehen + if (pContainer->CountTableAlias(sAliasName, m_nAliasNum)) + { + sAliasName += ::rtl::OUString('_'); + sAliasName += ::rtl::OUString::valueOf(m_nAliasNum); + } + + + sAliasName = String(sAliasName).EraseAllChars('"'); + SetAliasName(sAliasName); + // SetAliasName reicht das als WinName weiter, dadurch benutzt es die Basisklasse + // reset the title + m_aTitle.SetText( pWinData->GetWinName() ); + m_aTitle.Show(); + + if (!bSuccess) + { // es soll nur ein Dummy-Window aufgemacht werden ... + DBG_ASSERT(GetAliasName().getLength(), "OQueryTableWindow::Init : kein Alias- UND kein Tabellenname geht nicht !"); + // .. aber das braucht wenigstens einen Alias + + // ::com::sun::star::form::ListBox anlegen + if (!m_pListBox) + m_pListBox = CreateListBox(); + + // Titel setzen + m_aTitle.SetText(GetAliasName()); + m_aTitle.Show(); + + clearListBox(); + // neu zu fuellen brauche ich die nicht, da ich ja keine Tabelle habe + m_pListBox->Show(); + } + + getTableView()->getDesignView()->getController().InvalidateFeature(ID_BROWSER_QUERY_EXECUTE); + return bSuccess; +} +// ----------------------------------------------------------------------------- +void* OQueryTableWindow::createUserData(const Reference< XPropertySet>& _xColumn,bool _bPrimaryKey) +{ + OTableFieldInfo* pInfo = new OTableFieldInfo(); + pInfo->SetKey(_bPrimaryKey ? TAB_PRIMARY_FIELD : TAB_NORMAL_FIELD); + if ( _xColumn.is() ) + pInfo->SetDataType(::comphelper::getINT32(_xColumn->getPropertyValue(PROPERTY_TYPE))); + return pInfo; +} +// ----------------------------------------------------------------------------- +void OQueryTableWindow::deleteUserData(void*& _pUserData) +{ + delete static_cast<OTableFieldInfo*>(_pUserData); + _pUserData = NULL; +} +//------------------------------------------------------------------------------ +void OQueryTableWindow::OnEntryDoubleClicked(SvLBoxEntry* pEntry) +{ + DBG_ASSERT(pEntry != NULL, "OQueryTableWindow::OnEntryDoubleClicked : pEntry darf nicht NULL sein !"); + // man koennte das auch abfragen und dann ein return hinsetzen, aber so weist es vielleicht auf Fehler bei Aufrufer hin + + if (getTableView()->getDesignView()->getController().isReadOnly()) + return; + + OTableFieldInfo* pInf = static_cast<OTableFieldInfo*>(pEntry->GetUserData()); + DBG_ASSERT(pInf != NULL, "OQueryTableWindow::OnEntryDoubleClicked : Feld hat keine FieldInfo !"); + + // eine DragInfo aufbauen + OTableFieldDescRef aInfo = new OTableFieldDesc(GetTableName(),m_pListBox->GetEntryText(pEntry)); + aInfo->SetTabWindow(this); + aInfo->SetAlias(GetAliasName()); + aInfo->SetFieldIndex(m_pListBox->GetModel()->GetAbsPos(pEntry)); + aInfo->SetDataType(pInf->GetDataType()); + + // und das entsprechende Feld einfuegen + static_cast<OQueryTableView*>(getTableView())->InsertField(aInfo); +} + +//------------------------------------------------------------------------------ +sal_Bool OQueryTableWindow::ExistsField(const ::rtl::OUString& strFieldName, OTableFieldDescRef& rInfo) +{ + DBG_ASSERT(m_pListBox != NULL, "OQueryTableWindow::ExistsField : habe keine ::com::sun::star::form::ListBox !"); + OSL_ENSURE(rInfo.is(),"OQueryTableWindow::ExistsField: invlid argument for OTableFieldDescRef!"); + Reference< XConnection> xConnection = getTableView()->getDesignView()->getController().getConnection(); + sal_Bool bExists = sal_False; + if(xConnection.is()) + { + SvLBoxEntry* pEntry = m_pListBox->First(); + try + { + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers()); + + while (pEntry) + { + if (bCase(strFieldName,::rtl::OUString(m_pListBox->GetEntryText(pEntry)))) + { + OTableFieldInfo* pInf = static_cast<OTableFieldInfo*>(pEntry->GetUserData()); + DBG_ASSERT(pInf != NULL, "OQueryTableWindow::ExistsField : Feld hat keine FieldInfo !"); + + rInfo->SetTabWindow(this); + rInfo->SetField(strFieldName); + rInfo->SetTable(GetTableName()); + rInfo->SetAlias(GetAliasName()); + rInfo->SetFieldIndex(m_pListBox->GetModel()->GetAbsPos(pEntry)); + rInfo->SetDataType(pInf->GetDataType()); + bExists = sal_True; + break; + } + pEntry = m_pListBox->Next(pEntry); + } + } + catch(SQLException&) + { + } + } + + return bExists; +} + +//------------------------------------------------------------------------------ +sal_Bool OQueryTableWindow::ExistsAVisitedConn() const +{ + return static_cast<const OQueryTableView*>(getTableView())->ExistsAVisitedConn(this); +} + +//------------------------------------------------------------------------------ +void OQueryTableWindow::KeyInput( const KeyEvent& rEvt ) +{ + OTableWindow::KeyInput( rEvt ); +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QTableWindow.hxx b/dbaccess/source/ui/querydesign/QTableWindow.hxx new file mode 100644 index 000000000000..deaad8621808 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QTableWindow.hxx @@ -0,0 +1,94 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QUERY_TABLEWINDOW_HXX +#define DBAUI_QUERY_TABLEWINDOW_HXX + +#include "TableWindow.hxx" +#include "QTableWindowData.hxx" +#include "TableFieldDescription.hxx" +#include <tools/rtti.hxx> + +namespace dbaui +{ + //================================================================== + class OQueryTableWindow : public OTableWindow + { + sal_Int32 m_nAliasNum; + ::rtl::OUString m_strInitialAlias; + public: + OQueryTableWindow( Window* pParent, const TTableWindowData::value_type& pTabWinData, sal_Unicode* pszInitialAlias = NULL ); + virtual ~OQueryTableWindow(); + + ::rtl::OUString GetAliasName() const + { + return static_cast<OQueryTableWindowData*>(GetData().get())->GetAliasName(); + } + void SetAliasName(const ::rtl::OUString& strNewAlias) + { + static_cast<OQueryTableWindowData*>(GetData().get())->SetAliasName(strNewAlias); + } + + // spaeter Constructor, die Basisklasse ERZEUGT beim ersten Aufruf die Listbox + virtual BOOL Init(); + + inline sal_Int32 GetAliasNum() const { return m_nAliasNum; } + + BOOL ExistsField(const ::rtl::OUString& strFieldName, OTableFieldDescRef& rInfo); + BOOL ExistsAVisitedConn() const; + + virtual ::rtl::OUString GetName() const { return GetWinName(); } + + protected: + virtual void KeyInput( const KeyEvent& rEvt ); + + virtual void OnEntryDoubleClicked(SvLBoxEntry* pEntry); + // wird aus dem DoubleClickHdl der ListBox heraus aufgerufen + /** delete the user data with the equal type as created within createUserData + @param _pUserData + The user data store in the listbox entries. Created with a call to createUserData. + _pUserData may be <NULL/>. + */ + virtual void deleteUserData(void*& _pUserData); + + /** creates user information that will be append at the ListBoxentry + @param _xColumn + The corresponding column, can be <NULL/>. + @param _bPrimaryKey + <TRUE/> when the column belongs to the primary key + @return + the user data which will be append at the listbox entry, may be <NULL/> + */ + virtual void* createUserData(const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet>& _xColumn, + bool _bPrimaryKey); + }; +} +#endif // DBAUI_QUERY_TABLEWINDOW_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QTableWindowData.cxx b/dbaccess/source/ui/querydesign/QTableWindowData.cxx new file mode 100644 index 000000000000..5fc047a9fbcf --- /dev/null +++ b/dbaccess/source/ui/querydesign/QTableWindowData.cxx @@ -0,0 +1,60 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "QTableWindowData.hxx" +#include <tools/debug.hxx> + + +using namespace dbaui; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::uno; + +DBG_NAME(OQueryTableWindowData) +//================================================================== +// class OQueryTableWindowData +//================================================================== +//------------------------------------------------------------------------------ +OQueryTableWindowData::OQueryTableWindowData(const ::rtl::OUString& _rComposedName, const ::rtl::OUString& rTableName, const ::rtl::OUString& rTableAlias ) + :OTableWindowData(NULL,_rComposedName, rTableName, rTableAlias) +{ + DBG_CTOR(OQueryTableWindowData,NULL); +} + +//------------------------------------------------------------------------------ +OQueryTableWindowData::~OQueryTableWindowData() +{ + DBG_DTOR(OQueryTableWindowData,NULL); +} +// ----------------------------------------------------------------------------- + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QTableWindowData.hxx b/dbaccess/source/ui/querydesign/QTableWindowData.hxx new file mode 100644 index 000000000000..9a54e738a764 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QTableWindowData.hxx @@ -0,0 +1,55 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QUERY_TABLEWINDOWDATA_HXX +#define DBAUI_QUERY_TABLEWINDOWDATA_HXX + +#include "TableWindowData.hxx" +#ifndef INCLUDED_VECTOR +#define INCLUDED_VECTOR +#include <vector> +#endif +#include <com/sun/star/io/XObjectOutputStream.hpp> +#include <com/sun/star/io/XObjectInputStream.hpp> + + +namespace dbaui +{ + class OQueryTableWindowData : public OTableWindowData + { + public: + explicit OQueryTableWindowData(const ::rtl::OUString& _rComposedName, const ::rtl::OUString& rTableName, const ::rtl::OUString& rTableAlias); + virtual ~OQueryTableWindowData(); + + ::rtl::OUString GetAliasName() { return GetWinName(); } + void SetAliasName(const ::rtl::OUString& rNewAlias) { SetWinName(rNewAlias); } + }; +} +#endif // DBAUI_QUERY_TABLEWINDOWDATA_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/Query.hrc b/dbaccess/source/ui/querydesign/Query.hrc new file mode 100644 index 000000000000..6fb9bb9ac5d0 --- /dev/null +++ b/dbaccess/source/ui/querydesign/Query.hrc @@ -0,0 +1,35 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QUERY_HRC +#define DBAUI_QUERY_HRC + +#define IMG_PRIMARY_KEY 1 +#define IMG_FOREIGN_KEY 2 + + +#endif // DBAUI_QUERY_HRC + diff --git a/dbaccess/source/ui/querydesign/QueryAddTabConnUndoAction.hxx b/dbaccess/source/ui/querydesign/QueryAddTabConnUndoAction.hxx new file mode 100644 index 000000000000..c0ef7d5ef1ef --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryAddTabConnUndoAction.hxx @@ -0,0 +1,63 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QUERYADDTABCONNUNDOACTION_HXX +#define DBAUI_QUERYADDTABCONNUNDOACTION_HXX + +#include "QueryTabConnUndoAction.hxx" + +namespace dbaui +{ + // ================================================================================================ + // OQueryAddTabConnUndoAction - Undo-Klasse fuer Einfuegen einer Connection + + class OQueryTableView; + class OQueryAddTabConnUndoAction : public OQueryTabConnUndoAction + { + public: + OQueryAddTabConnUndoAction(OQueryTableView* pOwner); + + virtual void Undo(); + virtual void Redo(); + }; + + // ================================================================================================ + // OQueryDelTabConnUndoAction - Undo-Klasse fuer Einfuegen einer Connection + + class OQueryDelTabConnUndoAction : public OQueryTabConnUndoAction + { + public: + OQueryDelTabConnUndoAction(OQueryTableView* pOwner); + + virtual void Undo(); + virtual void Redo(); + }; +} +#endif // DBAUI_QUERYADDTABCONNUNDOACTION_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryDesignFieldUndoAct.hxx b/dbaccess/source/ui/querydesign/QueryDesignFieldUndoAct.hxx new file mode 100644 index 000000000000..6cccdbcf9c34 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryDesignFieldUndoAct.hxx @@ -0,0 +1,161 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QUERYDESIGNFIELDUNDOACT_HXX +#define DBAUI_QUERYDESIGNFIELDUNDOACT_HXX + +#include "GeneralUndo.hxx" +#include "dbu_qry.hrc" +#include "SelectionBrowseBox.hxx" + + +namespace dbaui +{ + // ================================================================================================ + // OQueryDesignFieldUndoAct - Basisklasse fuer Undos in der Feldauflistung im Abfrageentwurf + + + class OQueryDesignFieldUndoAct : public OCommentUndoAction + { + protected: + OSelectionBrowseBox* pOwner; + USHORT m_nColumnPostion; + + virtual void Undo() = 0; + virtual void Redo() = 0; + + public: + OQueryDesignFieldUndoAct(OSelectionBrowseBox* pSelBrwBox, USHORT nCommentID); + virtual ~OQueryDesignFieldUndoAct(); + + inline void SetColumnPosition(USHORT _nColumnPostion) + { + m_nColumnPostion = _nColumnPostion; + OSL_ENSURE(m_nColumnPostion != BROWSER_INVALIDID,"Column position was not set add the undo action!"); + OSL_ENSURE(m_nColumnPostion < pOwner->GetColumnCount(),"Position outside the column count!"); + } + }; + + // ================================================================================================ + // OTabFieldCellModifiedUndoAct - Undo-Klasse fuer Aendern einer Zelle einer Spaltenbeschreibung + + class OTabFieldCellModifiedUndoAct : public OQueryDesignFieldUndoAct + { + protected: + String m_strNextCellContents; + sal_Int32 m_nCellIndex; + + public: + OTabFieldCellModifiedUndoAct(OSelectionBrowseBox* pSelBrwBox) + : OQueryDesignFieldUndoAct(pSelBrwBox, STR_QUERY_UNDO_MODIFY_CELL) + ,m_nCellIndex(BROWSER_INVALIDID){ } + + inline void SetCellContents(const String& str) { m_strNextCellContents = str; } + inline void SetCellIndex(sal_Int32 nIndex) { m_nCellIndex = nIndex; } + + virtual void Undo(); + virtual void Redo() { Undo(); } + }; + + // ================================================================================================ + // OTabFieldSizedUndoAct - Undo-Klasse fuer Aendern einer Spaltenbreite + + class OTabFieldSizedUndoAct : public OQueryDesignFieldUndoAct + { + protected: + long m_nNextWidth; + + public: + OTabFieldSizedUndoAct(OSelectionBrowseBox* pSelBrwBox) : OQueryDesignFieldUndoAct(pSelBrwBox, STR_QUERY_UNDO_SIZE_COLUMN), m_nNextWidth(0) { } + + inline void SetOriginalWidth(long nWidth) { m_nNextWidth = nWidth; } + + virtual void Undo(); + virtual void Redo() { Undo(); } + }; + + // ================================================================================================ + // OTabFieldUndoAct - Basisklasse fuer Undos in der Feldauflistung im Abfrageentwurf, die mit Veraendern einer kompletten Feldbeschreibung zu tun haben + + class OTabFieldUndoAct : public OQueryDesignFieldUndoAct + { + protected: + OTableFieldDescRef pDescr; // geloeschte Spaltenbeschreibung + + public: + OTabFieldUndoAct(OSelectionBrowseBox* pSelBrwBox, USHORT nCommentID) : OQueryDesignFieldUndoAct(pSelBrwBox, nCommentID) { } + + void SetTabFieldDescr(OTableFieldDescRef pDescription) { pDescr = pDescription; } + }; + + // ================================================================================================ + // OTabFieldDelUndoAct - Undo-Klasse fuer Loeschen eines Feldes + + class OTabFieldDelUndoAct : public OTabFieldUndoAct + { + protected: + virtual void Undo() { pOwner->EnterUndoMode();pOwner->InsertColumn(pDescr, m_nColumnPostion);pOwner->LeaveUndoMode(); } + virtual void Redo() { pOwner->EnterUndoMode();pOwner->RemoveColumn(pDescr->GetColumnId());pOwner->LeaveUndoMode(); } + + public: + OTabFieldDelUndoAct(OSelectionBrowseBox* pSelBrwBox) : OTabFieldUndoAct(pSelBrwBox, STR_QUERY_UNDO_TABFIELDDELETE) { } + }; + + // ================================================================================================ + // OTabFieldDelUndoAct - Undo-Klasse fuer Anlegen eines Feldes + + class OTabFieldCreateUndoAct : public OTabFieldUndoAct + { + protected: + virtual void Undo() { pOwner->EnterUndoMode();pOwner->RemoveColumn(pDescr->GetColumnId());pOwner->LeaveUndoMode();} + virtual void Redo() { pOwner->EnterUndoMode();pOwner->InsertColumn(pDescr, m_nColumnPostion);pOwner->LeaveUndoMode();} + + public: + OTabFieldCreateUndoAct(OSelectionBrowseBox* pSelBrwBox) : OTabFieldUndoAct(pSelBrwBox, STR_QUERY_UNDO_TABFIELDCREATE) { } + }; + + // ================================================================================================ + // OTabFieldMovedUndoAct - Undo-class when a field was moved inside the selection + + class OTabFieldMovedUndoAct : public OTabFieldUndoAct + { + protected: + virtual void Undo(); + virtual void Redo() + { + Undo(); + } + + public: + OTabFieldMovedUndoAct(OSelectionBrowseBox* pSelBrwBox) : OTabFieldUndoAct(pSelBrwBox, STR_QUERY_UNDO_TABFIELDMOVED) { } + }; +} +#endif // DBAUI_QUERYDESIGNFIELDUNDOACT_HXX + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryDesignUndoAction.hxx b/dbaccess/source/ui/querydesign/QueryDesignUndoAction.hxx new file mode 100644 index 000000000000..557a94c14204 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryDesignUndoAction.hxx @@ -0,0 +1,50 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QUERYDESIGNUNDOACTION_HXX +#define DBAUI_QUERYDESIGNUNDOACTION_HXX + +#include "GeneralUndo.hxx" + +namespace dbaui +{ + // ================================================================================================ + // OQueryDesignUndoAction - Undo-Basisklasse fuer Aktionen im graphischen Abfrageentwurf (ohne Feldliste) + + class OJoinTableView; + class OQueryDesignUndoAction : public OCommentUndoAction + { + protected: + OJoinTableView* m_pOwner; // in diesem Container spielt sich alles ab + + public: + OQueryDesignUndoAction(OJoinTableView* pOwner, USHORT nCommentID) : OCommentUndoAction(nCommentID), m_pOwner(pOwner) { } + }; +} +#endif // DBAUI_QUERYDESIGNUNDOACTION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryDesignView.cxx b/dbaccess/source/ui/querydesign/QueryDesignView.cxx new file mode 100644 index 000000000000..cd4fd7c016fc --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryDesignView.cxx @@ -0,0 +1,3216 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "QueryDesignView.hxx" +#include "QueryTableView.hxx" +#include "QTableWindow.hxx" +#include <vcl/toolbox.hxx> +#include "querycontroller.hxx" +#include <vcl/split.hxx> +#include <svl/undo.hxx> +#include <tools/diagnose_ex.h> +#include "adtabdlg.hxx" +#include <vcl/svapp.hxx> +#include <vcl/combobox.hxx> +#include <vcl/msgbox.hxx> +#include "browserids.hxx" +#include "SelectionBrowseBox.hxx" +#include "dbu_qry.hrc" +#include <unotools/configmgr.hxx> +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/dbexception.hxx> +#include <com/sun/star/i18n/XLocaleData.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <connectivity/PColumn.hxx> +#include "QTableConnection.hxx" +#include "ConnectionLine.hxx" +#include "ConnectionLineData.hxx" +#include "QTableConnectionData.hxx" +#include "dbustrings.hrc" +#include <comphelper/extract.hxx> +#include "UITools.hxx" +#include "querycontainerwindow.hxx" +#include "QueryTableView.hxx" +#include "sqlmessage.hxx" +#include <unotools/syslocale.hxx> + +using namespace ::dbaui; +using namespace ::utl; +using namespace ::connectivity; +using namespace ::dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; + +#define SQL_ISRULEOR2(pParseNode, e1,e2) ((pParseNode)->isRule() && (\ + (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e1) || \ + (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e2))) + +// here we define our functions used in the anonymous namespace to get our header file smaller +// please look at the book LargeScale C++ to know why +namespace +{ + static const ::rtl::OUString C_AND(RTL_CONSTASCII_USTRINGPARAM(" AND ")); + static const ::rtl::OUString C_OR(RTL_CONSTASCII_USTRINGPARAM(" OR ")); + + // forward declarations + sal_Bool InsertJoin( const OQueryDesignView* _pView, + const ::connectivity::OSQLParseNode *pNode); + + SqlParseError InstallFields(OQueryDesignView* _pView, + const ::connectivity::OSQLParseNode* pNode, + OJoinTableView::OTableWindowMap* pTabList ); + + SqlParseError GetGroupCriteria( OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode* pSelectRoot ); + + SqlParseError GetHavingCriteria(OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode* pSelectRoot, + sal_uInt16& rLevel ); + + SqlParseError GetOrderCriteria( OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode* pParseRoot ); + + SqlParseError AddFunctionCondition(OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode * pCondition, + const sal_uInt16 nLevel, + sal_Bool bHaving, + bool _bAddOrOnOneLine); + + //------------------------------------------------------------------------------ + ::rtl::OUString quoteTableAlias(sal_Bool _bQuote, const ::rtl::OUString& _sAliasName, const ::rtl::OUString& _sQuote) + { + ::rtl::OUString sRet; + if ( _bQuote && _sAliasName.getLength() ) + { + sRet = ::dbtools::quoteName(_sQuote,_sAliasName); + const static ::rtl::OUString sTableSeparater('.'); + sRet += sTableSeparater; + } + return sRet; + } + //------------------------------------------------------------------------------ + ::rtl::OUString getTableRange(const OQueryDesignView* _pView,const ::connectivity::OSQLParseNode* _pTableRef) + { + Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection(); + ::rtl::OUString sTableRange; + if ( _pTableRef ) + { + sTableRange = ::connectivity::OSQLParseNode::getTableRange(_pTableRef); + if ( !sTableRange.getLength() ) + _pTableRef->parseNodeToStr(sTableRange,xConnection,NULL,sal_False,sal_False); + } + return sTableRange; + } + //------------------------------------------------------------------------------ + void insertConnection(const OQueryDesignView* _pView,const EJoinType& _eJoinType,OTableFieldDescRef _aDragLeft,OTableFieldDescRef _aDragRight,bool _bNatural = false) + { + OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView()); + OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>( pTableView->GetTabConn(static_cast<OTableWindow*>(_aDragLeft->GetTabWindow()),static_cast<OTableWindow*>(_aDragRight->GetTabWindow()),true)); + + if ( !pConn ) + { + OQueryTableConnectionData* pInfoData = new OQueryTableConnectionData(); + TTableConnectionData::value_type aInfoData(pInfoData); + pInfoData->InitFromDrag(_aDragLeft, _aDragRight); + pInfoData->SetJoinType(_eJoinType); + + if ( _bNatural ) + { + aInfoData->ResetConnLines(); + pInfoData->setNatural(_bNatural); + try + { + Reference<XNameAccess> xReferencedTableColumns(aInfoData->getReferencedTable()->getColumns()); + Sequence< ::rtl::OUString> aSeq = aInfoData->getReferencingTable()->getColumns()->getElementNames(); + const ::rtl::OUString* pIter = aSeq.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); + for(;pIter != pEnd;++pIter) + { + if ( xReferencedTableColumns->hasByName(*pIter) ) + aInfoData->AppendConnLine(*pIter,*pIter); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + OQueryTableConnection aInfo(pTableView, aInfoData); + // da ein OQueryTableConnection-Objekt nie den Besitz der uebergebenen Daten uebernimmt, sondern sich nur den Zeiger merkt, + // ist dieser Zeiger auf eine lokale Variable hier unkritisch, denn aInfoData und aInfo haben die selbe Lebensdauer + pTableView->NotifyTabConnection( aInfo ); + } + else + { + ::rtl::OUString aSourceFieldName(_aDragLeft->GetField()); + ::rtl::OUString aDestFieldName(_aDragRight->GetField()); + // the connection could point on the other side + if(pConn->GetSourceWin() == _aDragRight->GetTabWindow()) + { + ::rtl::OUString aTmp(aSourceFieldName); + aSourceFieldName = aDestFieldName; + aDestFieldName = aTmp; + } + pConn->GetData()->AppendConnLine( aSourceFieldName,aDestFieldName); + pConn->UpdateLineList(); + // Modified-Flag + // SetModified(); + // 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->InvalidateConnection(); + } + } + //------------------------------------------------------------------------------ + ::rtl::OUString ParseCondition( OQueryController& rController + ,const ::connectivity::OSQLParseNode* pCondition + ,const ::rtl::OUString _sDecimal + ,const ::com::sun::star::lang::Locale& _rLocale + ,sal_uInt32 _nStartIndex) + { + ::rtl::OUString aCondition; + Reference< XConnection> xConnection = rController.getConnection(); + if ( xConnection.is() ) + { + sal_uInt32 nCount = pCondition->count(); + for(sal_uInt32 i = _nStartIndex ; i < nCount ; ++i) + pCondition->getChild(i)->parseNodeToPredicateStr(aCondition, + xConnection, + rController.getNumberFormatter(), + _rLocale, + static_cast<sal_Char>(_sDecimal.toChar()), + &rController.getParser().getContext()); + } + return aCondition; + } + //------------------------------------------------------------------------------ + SqlParseError FillOuterJoins(OQueryDesignView* _pView, + const ::connectivity::OSQLParseNode* pTableRefList) + { + SqlParseError eErrorCode = eOk; + sal_uInt32 nCount = pTableRefList->count(); + sal_Bool bError = sal_False; + for (sal_uInt32 i=0; !bError && i < nCount; ++i) + { + const ::connectivity::OSQLParseNode* pParseNode = pTableRefList->getChild(i); + const ::connectivity::OSQLParseNode* pJoinNode = NULL; + + if ( SQL_ISRULE( pParseNode, qualified_join ) || SQL_ISRULE( pParseNode, joined_table ) || SQL_ISRULE( pParseNode, cross_union ) ) + pJoinNode = pParseNode; + else if( SQL_ISRULE(pParseNode,table_ref) + && pParseNode->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}' + pJoinNode = pParseNode->getChild(2); + + if ( pJoinNode ) + { + if ( !InsertJoin(_pView,pJoinNode) ) + bError = sal_True; + } + } + // check if error occurred + if ( bError ) + eErrorCode = eIllegalJoin; + + return eErrorCode; + } + // ----------------------------------------------------------------------------- + + /** FillDragInfo fills the field description out of the table + */ + //------------------------------------------------------------------------------ + SqlParseError FillDragInfo( const OQueryDesignView* _pView, + const ::connectivity::OSQLParseNode* pColumnRef, + OTableFieldDescRef& _rDragInfo) + { + SqlParseError eErrorCode = eOk; + + sal_Bool bErg = sal_False; + + ::rtl::OUString aTableRange,aColumnName; + sal_uInt16 nCntAccount; + ::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator(); + rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange ); + + if ( aTableRange.getLength() ) + { + OQueryTableWindow* pSTW = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( aTableRange ); + bErg = (pSTW && pSTW->ExistsField( aColumnName, _rDragInfo ) ); + } + if ( !bErg ) + { + bErg = static_cast<OQueryTableView*>(_pView->getTableView())->FindTableFromField(aColumnName, _rDragInfo, nCntAccount); + if ( !bErg ) + bErg = _pView->HasFieldByAliasName(aColumnName, _rDragInfo); + } + if ( !bErg ) + { + eErrorCode = eColumnNotFound; + String sError(ModuleRes(STR_QRY_COLUMN_NOT_FOUND)); + sError.SearchAndReplaceAscii("$name$",aColumnName); + _pView->getController().appendError( sError ); + + try + { + Reference<XDatabaseMetaData> xMeta = _pView->getController().getConnection()->getMetaData(); + if ( xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() ) + _pView->getController().appendError( String( ModuleRes( STR_QRY_CHECK_CASESENSITIVE ) ) ); + } + catch(Exception&) + { + } + } + + return eErrorCode; + } + //------------------------------------------------------------------------------ + ::rtl::OUString BuildJoinCriteria( const Reference< XConnection>& _xConnection, + OConnectionLineDataVec* pLineDataList, + OQueryTableConnectionData* pData) + { + ::rtl::OUStringBuffer aCondition; + if ( _xConnection.is() ) + { + OConnectionLineDataVec::iterator aIter = pLineDataList->begin(); + OConnectionLineDataVec::iterator aEnd = pLineDataList->end(); + try + { + const Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData(); + const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString(); + const ::rtl::OUString sEqual(RTL_CONSTASCII_USTRINGPARAM(" = ")); + + for(;aIter != aEnd;++aIter) + { + OConnectionLineDataRef pLineData = *aIter; + if(aCondition.getLength()) + aCondition.append(C_AND); + aCondition.append(quoteTableAlias(sal_True,pData->GetAliasName(JTCS_FROM),aQuote)); + aCondition.append(::dbtools::quoteName(aQuote, pLineData->GetFieldName(JTCS_FROM) )); + aCondition.append(sEqual); + aCondition.append(quoteTableAlias(sal_True,pData->GetAliasName(JTCS_TO),aQuote)); + aCondition.append(::dbtools::quoteName(aQuote, pLineData->GetFieldName(JTCS_TO) )); + } + } + catch(SQLException&) + { + OSL_ASSERT(!"Failure while building Join criteria!"); + } + } + + return aCondition.makeStringAndClear(); + } + //------------------------------------------------------------------------------ + /** JoinCycle looks for a join cycle and append it to the string + @param _xConnection the connection + @param _pEntryConn the table connection which holds the data + @param _pEntryTabTo the corresponding table window + @param _rJoin the String which will contain the resulting string + */ + void JoinCycle( const Reference< XConnection>& _xConnection, + OQueryTableConnection* _pEntryConn, + const OQueryTableWindow* _pEntryTabTo, + ::rtl::OUString& _rJoin ) + { + OSL_ENSURE(_pEntryConn,"TableConnection can not be null!"); + + OQueryTableConnectionData* pData = static_cast< OQueryTableConnectionData*>(_pEntryConn->GetData().get()); + if ( pData->GetJoinType() != INNER_JOIN && _pEntryTabTo->ExistsAVisitedConn() ) + { + sal_Bool bBrace = sal_False; + if(_rJoin.getLength() && _rJoin.lastIndexOf(')') == (_rJoin.getLength()-1)) + { + bBrace = sal_True; + _rJoin = _rJoin.replaceAt(_rJoin.getLength()-1,1,::rtl::OUString(' ')); + } + (_rJoin += C_AND) += BuildJoinCriteria(_xConnection,pData->GetConnLineDataList(),pData); + if(bBrace) + _rJoin += ::rtl::OUString(')'); + _pEntryConn->SetVisited(sal_True); + } + } + //------------------------------------------------------------------------------ + ::rtl::OUString BuildTable( const Reference< XConnection>& _xConnection, + const OQueryTableWindow* pEntryTab, + bool _bForce = false + ) + { + ::rtl::OUString aDBName(pEntryTab->GetComposedName()); + + if( _xConnection.is() ) + { + try + { + Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData(); + + ::rtl::OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents( xMetaData, aDBName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation ); + ::rtl::OUString aTableListStr = ::dbtools::composeTableNameForSelect( _xConnection, sCatalog, sSchema, sTable ); + + ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString(); + if ( _bForce || isAppendTableAliasEnabled( _xConnection ) || pEntryTab->GetAliasName() != aDBName ) + { + aTableListStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ")); + if ( generateAsBeforeTableAlias( _xConnection ) ) + aTableListStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AS ")); + aTableListStr += ::dbtools::quoteName( aQuote, pEntryTab->GetAliasName() ); + } + aDBName = aTableListStr; + } + catch(const SQLException&) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + return aDBName; + } + //------------------------------------------------------------------------------ + ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection, + const ::rtl::OUString& rLh, + const ::rtl::OUString& rRh, + OQueryTableConnectionData* pData) + { + + String aErg(rLh); + if ( pData->isNatural() && pData->GetJoinType() != CROSS_JOIN ) + aErg.AppendAscii(" NATURAL "); + switch(pData->GetJoinType()) + { + case LEFT_JOIN: + aErg.AppendAscii(" LEFT OUTER "); + break; + case RIGHT_JOIN: + aErg.AppendAscii(" RIGHT OUTER "); + break; + case CROSS_JOIN: + OSL_ENSURE(!pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!"); + aErg.AppendAscii(" CROSS "); + break; + case INNER_JOIN: + OSL_ENSURE(pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!"); + aErg.AppendAscii(" INNER "); + break; + default: + aErg.AppendAscii(" FULL OUTER "); + break; + } + aErg.AppendAscii("JOIN "); + aErg += String(rRh); + if ( CROSS_JOIN != pData->GetJoinType() && !pData->isNatural() ) + { + aErg.AppendAscii(" ON "); + aErg += String(BuildJoinCriteria(_xConnection,pData->GetConnLineDataList(),pData)); + } + + return aErg; + } + //------------------------------------------------------------------------------ + ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection, + OQueryTableWindow* pLh, + OQueryTableWindow* pRh, + OQueryTableConnectionData* pData + ) + { + bool bForce = pData->GetJoinType() == CROSS_JOIN || pData->isNatural(); + return BuildJoin(_xConnection,BuildTable(_xConnection,pLh,bForce),BuildTable(_xConnection,pRh,bForce),pData); + } + //------------------------------------------------------------------------------ + ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection, + const ::rtl::OUString &rLh, + OQueryTableWindow* pRh, + OQueryTableConnectionData* pData + ) + { + return BuildJoin(_xConnection,rLh,BuildTable(_xConnection,pRh),pData); + } + //------------------------------------------------------------------------------ + ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection, + OQueryTableWindow* pLh, + const ::rtl::OUString &rRh, + OQueryTableConnectionData* pData + ) + { + return BuildJoin(_xConnection,BuildTable(_xConnection,pLh),rRh,pData); + } + //------------------------------------------------------------------------------ + void GetNextJoin( const Reference< XConnection>& _xConnection, + OQueryTableConnection* pEntryConn, + OQueryTableWindow* pEntryTabTo, + ::rtl::OUString &aJoin) + { + OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get()); + if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() ) + return; + + if(!aJoin.getLength()) + { + OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()); + aJoin = BuildJoin(_xConnection,pEntryTabFrom,pEntryTabTo,pEntryConnData); + } + else if(pEntryTabTo == pEntryConn->GetDestWin()) + { + aJoin = BuildJoin(_xConnection,aJoin,pEntryTabTo,pEntryConnData); + } + else if(pEntryTabTo == pEntryConn->GetSourceWin()) + { + aJoin = BuildJoin(_xConnection,pEntryTabTo,aJoin,pEntryConnData); + } + + pEntryConn->SetVisited(sal_True); + + // first search for the "to" window + const ::std::vector<OTableConnection*>* pConnections = pEntryConn->GetParent()->getTableConnections(); + ::std::vector<OTableConnection*>::const_iterator aIter = pConnections->begin(); + ::std::vector<OTableConnection*>::const_iterator aEnd = pConnections->end(); + for(;aIter != aEnd;++aIter) + { + OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(*aIter); + if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabTo || pNext->GetDestWin() == pEntryTabTo)) + { + OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabTo ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin()); + // exists there a connection to a OQueryTableWindow that holds a connection that has been already visited + JoinCycle(_xConnection,pNext,pEntryTab,aJoin); + if(!pNext->IsVisited()) + GetNextJoin(_xConnection,pNext,pEntryTab,aJoin); + } + } + + // when nothing found found look for the "from" window + if(aIter == aEnd) + { + OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()); + aIter = pConnections->begin(); + for(;aIter != aEnd;++aIter) + { + OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(*aIter); + if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabFrom || pNext->GetDestWin() == pEntryTabFrom)) + { + OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabFrom ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin()); + // exists there a connection to a OQueryTableWindow that holds a connection that has been already visited + JoinCycle(_xConnection,pNext,pEntryTab,aJoin); + if(!pNext->IsVisited()) + GetNextJoin(_xConnection,pNext,pEntryTab,aJoin); + } + } + } + } + //------------------------------------------------------------------------------ + SqlParseError InsertJoinConnection( const OQueryDesignView* _pView, + const ::connectivity::OSQLParseNode *pNode, + const EJoinType& _eJoinType, + const ::connectivity::OSQLParseNode *pLeftTable, + const ::connectivity::OSQLParseNode *pRightTable) + { + SqlParseError eErrorCode = eOk; + if (pNode->count() == 3 && // Ausdruck is geklammert + SQL_ISPUNCTUATION(pNode->getChild(0),"(") && + SQL_ISPUNCTUATION(pNode->getChild(2),")")) + { + eErrorCode = InsertJoinConnection(_pView,pNode->getChild(1), _eJoinType,pLeftTable,pRightTable); + } + else if (SQL_ISRULEOR2(pNode,search_condition,boolean_term) && // AND/OR-Verknuepfung: + pNode->count() == 3) + { + // nur AND Verknüpfung zulassen + if (!SQL_ISTOKEN(pNode->getChild(1),AND)) + eErrorCode = eIllegalJoinCondition; + else if ( eOk == (eErrorCode = InsertJoinConnection(_pView,pNode->getChild(0), _eJoinType,pLeftTable,pRightTable)) ) + eErrorCode = InsertJoinConnection(_pView,pNode->getChild(2), _eJoinType,pLeftTable,pRightTable); + } + else if (SQL_ISRULE(pNode,comparison_predicate)) + { + // only the comparison of columns is allowed + DBG_ASSERT(pNode->count() == 3,"OQueryDesignView::InsertJoinConnection: Fehler im Parse Tree"); + if (!(SQL_ISRULE(pNode->getChild(0),column_ref) && + SQL_ISRULE(pNode->getChild(2),column_ref) && + pNode->getChild(1)->getNodeType() == SQL_NODE_EQUAL)) + { + String sError(ModuleRes(STR_QRY_JOIN_COLUMN_COMPARE)); + _pView->getController().appendError( sError ); + return eIllegalJoin; + } + + OTableFieldDescRef aDragLeft = new OTableFieldDesc(); + OTableFieldDescRef aDragRight = new OTableFieldDesc(); + if ( eOk != ( eErrorCode = FillDragInfo(_pView,pNode->getChild(0),aDragLeft)) || + eOk != ( eErrorCode = FillDragInfo(_pView,pNode->getChild(2),aDragRight))) + return eErrorCode; + + if ( pLeftTable ) + { + OQueryTableWindow* pLeftWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pLeftTable->getByRule(OSQLParseNode::table_ref) )); + if ( pLeftWindow == aDragLeft->GetTabWindow() ) + insertConnection(_pView,_eJoinType,aDragLeft,aDragRight); + else + insertConnection(_pView,_eJoinType,aDragRight,aDragLeft); + } + else + insertConnection(_pView,_eJoinType,aDragLeft,aDragRight); + } + else + eErrorCode = eIllegalJoin; + return eErrorCode; + } + //------------------------------------------------------------------------------ + sal_Bool GetInnerJoinCriteria( const OQueryDesignView* _pView, + const ::connectivity::OSQLParseNode *pCondition) + { + return InsertJoinConnection(_pView,pCondition, INNER_JOIN,NULL,NULL) != eOk; + } + //------------------------------------------------------------------------------ + ::rtl::OUString GenerateSelectList( const OQueryDesignView* _pView, + OTableFields& _rFieldList, + sal_Bool bAlias) + { + Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection(); + if ( !xConnection.is() ) + return ::rtl::OUString(); + + ::rtl::OUStringBuffer aTmpStr,aFieldListStr; + + sal_Bool bAsterix = sal_False; + int nVis = 0; + OTableFields::iterator aIter = _rFieldList.begin(); + OTableFields::iterator aEnd = _rFieldList.end(); + for(;aIter != aEnd;++aIter) + { + OTableFieldDescRef pEntryField = *aIter; + if ( pEntryField->IsVisible() ) + { + if ( pEntryField->GetField().toChar() == '*' ) + bAsterix = sal_True; + ++nVis; + } + } + if(nVis == 1) + bAsterix = sal_False; + + try + { + const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString(); + + OJoinTableView::OTableWindowMap* pTabList = _pView->getTableView()->GetTabWinMap(); + + const static ::rtl::OUString sFieldSeparator(RTL_CONSTASCII_USTRINGPARAM(", ")); + const static ::rtl::OUString s_sAs(RTL_CONSTASCII_USTRINGPARAM(" AS ")); + + aIter = _rFieldList.begin(); + for(;aIter != aEnd;++aIter) + { + OTableFieldDescRef pEntryField = *aIter; + ::rtl::OUString rFieldName = pEntryField->GetField(); + if ( rFieldName.getLength() && pEntryField->IsVisible() ) + { + aTmpStr = ::rtl::OUString(); + const ::rtl::OUString rAlias = pEntryField->GetAlias(); + const ::rtl::OUString rFieldAlias = pEntryField->GetFieldAlias(); + + aTmpStr.append(quoteTableAlias((bAlias || bAsterix),rAlias,aQuote)); + + // if we have a none numeric field, the table alias could be in the name + // otherwise we are not allowed to do this (e.g. 0.1 * PRICE ) + if ( !pEntryField->isOtherFunction() ) + { + // we have to look if we have alias.* here but before we have to check if the column doesn't already exist + String sTemp = rFieldName; + OTableFieldDescRef aInfo = new OTableFieldDesc(); + OJoinTableView::OTableWindowMap::iterator tableIter = pTabList->begin(); + OJoinTableView::OTableWindowMap::iterator tableEnd = pTabList->end(); + sal_Bool bFound = sal_False; + for(;!bFound && tableIter != tableEnd ;++tableIter) + { + OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(tableIter->second); + + bFound = pTabWin->ExistsField( rFieldName, aInfo ); + if ( bFound ) + rFieldName = aInfo->GetField(); + } + if ( ( rFieldName.toChar() != '*' ) && ( rFieldName.indexOf( aQuote ) == -1 ) ) + { + OSL_ENSURE(pEntryField->GetTable().getLength(),"No table field name!"); + aTmpStr.append(::dbtools::quoteName(aQuote, rFieldName)); + } + else + aTmpStr.append(rFieldName); + } + else + aTmpStr.append(rFieldName); + + if ( pEntryField->isAggreateFunction() ) + { + DBG_ASSERT(pEntryField->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-("); + ::rtl::OUStringBuffer aTmpStr2( pEntryField->GetFunction()); + aTmpStr2.appendAscii("("); + aTmpStr2.append(aTmpStr.makeStringAndClear()); + aTmpStr2.appendAscii(")"); + aTmpStr = aTmpStr2; + } + + if (rFieldAlias.getLength() && + (rFieldName.toChar() != '*' || + pEntryField->isNumericOrAggreateFunction() || + pEntryField->isOtherFunction())) + { + aTmpStr.append(s_sAs); + aTmpStr.append(::dbtools::quoteName(aQuote, rFieldAlias)); + } + aFieldListStr.append(aTmpStr.makeStringAndClear()); + aFieldListStr.append(sFieldSeparator); + } + } + if(aFieldListStr.getLength()) + aFieldListStr.setLength(aFieldListStr.getLength()-2); + } + catch(SQLException&) + { + OSL_ASSERT(!"Failure while building select list!"); + } + return aFieldListStr.makeStringAndClear(); + } + //------------------------------------------------------------------------------ + sal_Bool GenerateCriterias( OQueryDesignView* _pView, + ::rtl::OUStringBuffer& rRetStr, + ::rtl::OUStringBuffer& rHavingStr, + OTableFields& _rFieldList, + sal_Bool bMulti ) + { + // * darf keine Filter enthalten : habe ich die entsprechende Warnung schon angezeigt ? + sal_Bool bCritsOnAsterikWarning = sal_False; // ** TMFS ** + + ::rtl::OUString aFieldName,aCriteria,aWhereStr,aHavingStr,aWork/*,aOrderStr*/; + // Zeilenweise werden die Ausdr"ucke mit AND verknuepft + sal_uInt16 nMaxCriteria = 0; + OTableFields::iterator aIter = _rFieldList.begin(); + OTableFields::iterator aEnd = _rFieldList.end(); + for(;aIter != aEnd;++aIter) + { + nMaxCriteria = ::std::max<sal_uInt16>(nMaxCriteria,(sal_uInt16)(*aIter)->GetCriteria().size()); + } + Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection(); + if(!xConnection.is()) + return FALSE; + try + { + const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString(); + const IParseContext& rContext = static_cast<OQueryController&>(_pView->getController()).getParser().getContext(); + + for (sal_uInt16 i=0 ; i < nMaxCriteria ; i++) + { + aHavingStr = aWhereStr = ::rtl::OUString(); + + for(aIter = _rFieldList.begin();aIter != aEnd;++aIter) + { + OTableFieldDescRef pEntryField = *aIter; + aFieldName = pEntryField->GetField(); + + if (!aFieldName.getLength()) + continue; + aCriteria = pEntryField->GetCriteria( i ); + if ( aCriteria.getLength() ) + { + // * is not allowed to contain any filter, only when used in combination an aggregate function + if ( aFieldName.toChar() == '*' && pEntryField->isNoneFunction() ) + { + // only show the messagebox the first time + if (!bCritsOnAsterikWarning) + ErrorBox(_pView, ModuleRes( ERR_QRY_CRITERIA_ON_ASTERISK)).Execute(); + bCritsOnAsterikWarning = sal_True; + continue; + } + aWork = ::rtl::OUString(); + + + aWork += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote); + + if ( (pEntryField->GetFunctionType() & (FKT_OTHER|FKT_NUMERIC)) || (aFieldName.toChar() == '*') ) + aWork += aFieldName; + else + aWork += ::dbtools::quoteName(aQuote, aFieldName); + + if ( pEntryField->isAggreateFunction() || pEntryField->IsGroupBy() ) + { + if (!aHavingStr.getLength()) // noch keine Kriterien + aHavingStr += ::rtl::OUString('('); // Klammern + else + aHavingStr += C_AND; + + if ( pEntryField->isAggreateFunction() ) + { + OSL_ENSURE(pEntryField->GetFunction().getLength(),"No function name for aggregate given!"); + aHavingStr += pEntryField->GetFunction(); + aHavingStr += ::rtl::OUString('('); // Klammern + aHavingStr += aWork; + aHavingStr += ::rtl::OUString(')'); // Klammern + } + else + aHavingStr += aWork; + + ::rtl::OUString aTmp = aCriteria; + ::rtl::OUString aErrorMsg; + Reference<XPropertySet> xColumn; + ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn)); + if (pParseNode.get()) + { + if (bMulti && !(pEntryField->isOtherFunction() || (aFieldName.toChar() == '*'))) + pParseNode->replaceNodeValue(pEntryField->GetAlias(),aFieldName); + ::rtl::OUString sHavingStr = aHavingStr; + + sal_uInt32 nCount = pParseNode->count(); + for( sal_uInt32 node = 1 ; node < nCount ; ++node) + pParseNode->getChild(node)->parseNodeToStr( sHavingStr, + xConnection, + &rContext, + sal_False, + !pEntryField->isOtherFunction()); + aHavingStr = sHavingStr; + } + else + aHavingStr += aCriteria; + } + else + { + if ( !aWhereStr.getLength() ) // noch keine Kriterien + aWhereStr += ::rtl::OUString('('); // Klammern + else + aWhereStr += C_AND; + + aWhereStr += ::rtl::OUString(' '); + // aCriteria could have some german numbers so I have to be sure here + ::rtl::OUString aTmp = aCriteria; + ::rtl::OUString aErrorMsg; + Reference<XPropertySet> xColumn; + ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode( _pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn)); + if (pParseNode.get()) + { + if (bMulti && !(pEntryField->isOtherFunction() || (aFieldName.toChar() == '*'))) + pParseNode->replaceNodeValue(pEntryField->GetAlias(),aFieldName); + ::rtl::OUString aWhere = aWhereStr; + pParseNode->parseNodeToStr( aWhere, + xConnection, + &rContext, + sal_False, + !pEntryField->isOtherFunction() ); + aWhereStr = aWhere; + } + else + { + aWhereStr += aWork; + aWhereStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("=")); + aWhereStr += aCriteria; + } + } + } + // nur einmal für jedes Feld + else if ( !i && pEntryField->isCondition() ) + { + if (!aWhereStr.getLength()) // noch keine Kriterien + aWhereStr += ::rtl::OUString('('); // Klammern + else + aWhereStr += C_AND; + aWhereStr += pEntryField->GetField(); + } + } + if (aWhereStr.getLength()) + { + aWhereStr += ::rtl::OUString(')'); // Klammern zu fuer 'AND' Zweig + if (rRetStr.getLength()) // schon Feldbedingungen ? + rRetStr.append(C_OR); + else // Klammern auf fuer 'OR' Zweig + rRetStr.append(sal_Unicode('(')); + rRetStr.append(aWhereStr); + } + if (aHavingStr.getLength()) + { + aHavingStr += ::rtl::OUString(')'); // Klammern zu fuer 'AND' Zweig + if (rHavingStr.getLength()) // schon Feldbedingungen ? + rHavingStr.append(C_OR); + else // Klammern auf fuer 'OR' Zweig + rHavingStr.append(sal_Unicode('(')); + rHavingStr.append(aHavingStr); + } + } + + if (rRetStr.getLength()) + rRetStr.append(sal_Unicode(')')); // Klammern zu fuer 'OR' Zweig + if (rHavingStr.getLength()) + rHavingStr.append(sal_Unicode(')')); // Klammern zu fuer 'OR' Zweig + } + catch(SQLException&) + { + OSL_ASSERT(!"Failure while building where clause!"); + } + return sal_True; + } + //------------------------------------------------------------------------------ + SqlParseError GenerateOrder( OQueryDesignView* _pView, + OTableFields& _rFieldList, + sal_Bool bMulti, + ::rtl::OUString& _rsRet) + { + const OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); + Reference< XConnection> xConnection = rController.getConnection(); + if ( !xConnection.is() ) + return eNoConnection; + + SqlParseError eErrorCode = eOk; + + ::rtl::OUString aColumnName; + ::rtl::OUString aWorkStr; + try + { + const bool bColumnAliasInOrderBy = rController.getSdbMetaData().supportsColumnAliasInOrderBy(); + Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString(); + // * darf keine Filter enthalten : habe ich die entsprechende Warnung schon angezeigt ? + sal_Bool bCritsOnAsterikWarning = sal_False; // ** TMFS ** + OTableFields::iterator aIter = _rFieldList.begin(); + OTableFields::iterator aEnd = _rFieldList.end(); + for(;aIter != aEnd;++aIter) + { + OTableFieldDescRef pEntryField = *aIter; + EOrderDir eOrder = pEntryField->GetOrderDir(); + + // nur wenn eine Sortierung und ein Tabellenname vorhanden ist-> erzeugen + // sonst werden die Expressions vom Order By im GenerateCriteria mit erzeugt + if ( eOrder != ORDER_NONE ) + { + aColumnName = pEntryField->GetField(); + if(aColumnName.toChar() == '*') + { + // die entsprechende MessageBox nur beim ersten mal anzeigen + if (!bCritsOnAsterikWarning) + ErrorBox(_pView, ModuleRes( ERR_QRY_ORDERBY_ON_ASTERISK)).Execute(); + bCritsOnAsterikWarning = sal_True; + continue; + } + + if ( bColumnAliasInOrderBy && pEntryField->GetFieldAlias().getLength() ) + { + aWorkStr += ::dbtools::quoteName(aQuote, pEntryField->GetFieldAlias()); + } + else if ( pEntryField->isNumericOrAggreateFunction() ) + { + DBG_ASSERT(pEntryField->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-("); + aWorkStr += pEntryField->GetFunction(); + aWorkStr += ::rtl::OUString('('); + aWorkStr += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote); + // only quote column name when we don't have a numeric + if ( pEntryField->isNumeric() ) + aWorkStr += aColumnName; + else + aWorkStr += ::dbtools::quoteName(aQuote, aColumnName); + + aWorkStr += ::rtl::OUString(')'); + } + else if ( pEntryField->isOtherFunction() ) + { + aWorkStr += aColumnName; + } + else + { + aWorkStr += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote); + aWorkStr += ::dbtools::quoteName(aQuote, aColumnName); + } + aWorkStr += ::rtl::OUString(' '); + aWorkStr += String::CreateFromAscii( ";ASC;DESC" ).GetToken( (USHORT)eOrder ); + aWorkStr += ::rtl::OUString(','); + } + } + + { + String sTemp(aWorkStr); + sTemp.EraseTrailingChars( ',' ); + aWorkStr = sTemp; + } + + if ( aWorkStr.getLength() ) + { + const sal_Int32 nMaxOrder = xMetaData->getMaxColumnsInOrderBy(); + String sToken(aWorkStr); + if ( nMaxOrder && nMaxOrder < sToken.GetTokenCount(',') ) + eErrorCode = eStatementTooLong; + else + { + _rsRet = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ORDER BY ")); + _rsRet += aWorkStr; + } + } + } + catch(SQLException&) + { + OSL_ASSERT(!"Failure while building group by!"); + } + + return eErrorCode; + } + + //------------------------------------------------------------------------------ + void GenerateInnerJoinCriterias(const Reference< XConnection>& _xConnection, + ::rtl::OUString& _rJoinCrit, + const ::std::vector<OTableConnection*>* _pConnList) + { + ::std::vector<OTableConnection*>::const_iterator aIter = _pConnList->begin(); + ::std::vector<OTableConnection*>::const_iterator aEnd = _pConnList->end(); + for(;aIter != aEnd;++aIter) + { + const OQueryTableConnection* pEntryConn = static_cast<const OQueryTableConnection*>(*aIter); + OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get()); + if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() ) + { + if(_rJoinCrit.getLength()) + _rJoinCrit += C_AND; + _rJoinCrit += BuildJoinCriteria(_xConnection,pEntryConnData->GetConnLineDataList(),pEntryConnData); + } + } + } + //------------------------------------------------------------------------------ + void searchAndAppendName(const Reference< XConnection>& _xConnection, + const OQueryTableWindow* _pTableWindow, + ::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess>& _rTableNames, + ::rtl::OUString& _rsTableListStr + ) + { + ::rtl::OUString sTabName(BuildTable(_xConnection,_pTableWindow)); + + if(_rTableNames.find(sTabName) == _rTableNames.end()) + { + _rTableNames[sTabName] = sal_True; + _rsTableListStr += sTabName; + _rsTableListStr += ::rtl::OUString(','); + } + } + //------------------------------------------------------------------------------ + ::rtl::OUString GenerateFromClause( const Reference< XConnection>& _xConnection, + const OQueryTableView::OTableWindowMap* pTabList, + const ::std::vector<OTableConnection*>* pConnList + ) + { + + ::rtl::OUString aTableListStr; + // wird gebraucht um sicher zustelllen das eine Tabelle nicht doppelt vorkommt + ::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess> aTableNames; + + // generate outer join clause in from + if(!pConnList->empty()) + { + ::std::vector<OTableConnection*>::const_iterator aIter = pConnList->begin(); + ::std::vector<OTableConnection*>::const_iterator aEnd = pConnList->end(); + ::std::map<OTableWindow*,sal_Int32> aConnectionCount; + for(;aIter != aEnd;++aIter) + { + static_cast<OQueryTableConnection*>(*aIter)->SetVisited(sal_False); + if ( aConnectionCount.find((*aIter)->GetSourceWin()) == aConnectionCount.end() ) + aConnectionCount.insert(::std::map<OTableWindow*,sal_Int32>::value_type((*aIter)->GetSourceWin(),0)); + else + aConnectionCount[(*aIter)->GetSourceWin()]++; + if ( aConnectionCount.find((*aIter)->GetDestWin()) == aConnectionCount.end() ) + aConnectionCount.insert(::std::map<OTableWindow*,sal_Int32>::value_type((*aIter)->GetDestWin(),0)); + else + aConnectionCount[(*aIter)->GetDestWin()]++; + } + ::std::multimap<sal_Int32 , OTableWindow*> aMulti; + ::std::map<OTableWindow*,sal_Int32>::iterator aCountIter = aConnectionCount.begin(); + ::std::map<OTableWindow*,sal_Int32>::iterator aCountEnd = aConnectionCount.end(); + for(;aCountIter != aCountEnd;++aCountIter) + { + aMulti.insert(::std::multimap<sal_Int32 , OTableWindow*>::value_type(aCountIter->second,aCountIter->first)); + } + + const sal_Bool bUseEscape = ::dbtools::getBooleanDataSourceSetting( _xConnection, PROPERTY_OUTERJOINESCAPE ); + ::std::multimap<sal_Int32 , OTableWindow*>::reverse_iterator aRIter = aMulti.rbegin(); + ::std::multimap<sal_Int32 , OTableWindow*>::reverse_iterator aREnd = aMulti.rend(); + for(;aRIter != aREnd;++aRIter) + { + ::std::vector<OTableConnection*>::const_iterator aConIter = aRIter->second->getTableView()->getTableConnections(aRIter->second); + for(;aConIter != aEnd;++aConIter) + { + OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(*aConIter); + if(!pEntryConn->IsVisited() && pEntryConn->GetSourceWin() == aRIter->second ) + { + ::rtl::OUString aJoin; + GetNextJoin(_xConnection,pEntryConn,static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()),aJoin); + + if(aJoin.getLength()) + { + // insert tables into table list to avoid double entries + OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()); + OQueryTableWindow* pEntryTabTo = static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()); + + ::rtl::OUString sTabName(BuildTable(_xConnection,pEntryTabFrom)); + if(aTableNames.find(sTabName) == aTableNames.end()) + aTableNames[sTabName] = sal_True; + sTabName = BuildTable(_xConnection,pEntryTabTo); + if(aTableNames.find(sTabName) == aTableNames.end()) + aTableNames[sTabName] = sal_True; + + ::rtl::OUString aStr; + switch(static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get())->GetJoinType()) + { + case LEFT_JOIN: + case RIGHT_JOIN: + case FULL_JOIN: + { + // create outer join + if ( bUseEscape ) + aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("{ OJ ")); + aStr += aJoin; + if ( bUseEscape ) + aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" }")); + } + break; + default: + aStr += aJoin; + break; + } + aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(",")); + aTableListStr += aStr; + } + } + } + } + + // and now all inner joins + aIter = pConnList->begin(); + for(;aIter != aEnd;++aIter) + { + OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(*aIter); + if(!pEntryConn->IsVisited()) + { + searchAndAppendName(_xConnection, + static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()), + aTableNames, + aTableListStr); + + searchAndAppendName(_xConnection, + static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()), + aTableNames, + aTableListStr); + } + } + } + // all tables that haven't a connection to anyone + OQueryTableView::OTableWindowMap::const_iterator aTabIter = pTabList->begin(); + OQueryTableView::OTableWindowMap::const_iterator aTabEnd = pTabList->end(); + for(;aTabIter != aTabEnd;++aTabIter) + { + const OQueryTableWindow* pEntryTab = static_cast<const OQueryTableWindow*>(aTabIter->second); + if(!pEntryTab->ExistsAConn()) + { + aTableListStr += BuildTable(_xConnection,pEntryTab); + aTableListStr += ::rtl::OUString(','); + } + } + + if(aTableListStr.getLength()) + aTableListStr = aTableListStr.replaceAt(aTableListStr.getLength()-1,1, ::rtl::OUString() ); + return aTableListStr; + } + //------------------------------------------------------------------------------ + ::rtl::OUString GenerateGroupBy(const OQueryDesignView* _pView,OTableFields& _rFieldList, sal_Bool bMulti ) + { + OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); + const Reference< XConnection> xConnection = rController.getConnection(); + if(!xConnection.is()) + return ::rtl::OUString(); + + ::std::map< rtl::OUString,bool> aGroupByNames; + + ::rtl::OUString aGroupByStr; + try + { + const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString(); + + OTableFields::iterator aIter = _rFieldList.begin(); + OTableFields::iterator aEnd = _rFieldList.end(); + for(;aIter != aEnd;++aIter) + { + OTableFieldDescRef pEntryField = *aIter; + if ( pEntryField->IsGroupBy() ) + { + DBG_ASSERT(pEntryField->GetField().getLength(),"Kein FieldName vorhanden!;-("); + ::rtl::OUString sGroupByPart = quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote); + + // only quote the field name when it isn't calculated + if ( pEntryField->isNoneFunction() ) + { + sGroupByPart += ::dbtools::quoteName(aQuote, pEntryField->GetField()); + } + else + { + ::rtl::OUString aTmp = pEntryField->GetField(); + ::rtl::OUString aErrorMsg; + Reference<XPropertySet> xColumn; + ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn)); + if (pParseNode.get()) + { + ::rtl::OUString sGroupBy; + pParseNode->getChild(0)->parseNodeToStr( sGroupBy, + xConnection, + &rController.getParser().getContext(), + sal_False, + !pEntryField->isOtherFunction()); + sGroupByPart += sGroupBy; + } + else + sGroupByPart += pEntryField->GetField(); + } + if ( aGroupByNames.find(sGroupByPart) == aGroupByNames.end() ) + { + aGroupByNames.insert(::std::map< rtl::OUString,bool>::value_type(sGroupByPart,true)); + aGroupByStr += sGroupByPart; + aGroupByStr += ::rtl::OUString(','); + } + } + } + if ( aGroupByStr.getLength() ) + { + aGroupByStr = aGroupByStr.replaceAt(aGroupByStr.getLength()-1,1, ::rtl::OUString(' ') ); + ::rtl::OUString aGroupByStr2(RTL_CONSTASCII_USTRINGPARAM(" GROUP BY ")); + aGroupByStr2 += aGroupByStr; + aGroupByStr = aGroupByStr2; + } + } + catch(SQLException&) + { + OSL_ASSERT(!"Failure while building group by!"); + } + return aGroupByStr; + } + // ----------------------------------------------------------------------------- + SqlParseError GetORCriteria(OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode * pCondition, + sal_uInt16& nLevel , + sal_Bool bHaving = sal_False, + bool bAddOrOnOneLine = false); + // ----------------------------------------------------------------------------- + SqlParseError GetSelectionCriteria( OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode* pNode, + sal_uInt16& rLevel ) + { + if (!SQL_ISRULE(pNode, select_statement)) + return eNoSelectStatement; + + // nyi: mehr Pruefung auf korrekte Struktur! + pNode = pNode ? pNode->getChild(3)->getChild(1) : NULL; + // no where clause found + if (!pNode || pNode->isLeaf()) + return eOk; + + // Naechster freier Satz ... + SqlParseError eErrorCode = eOk; + ::connectivity::OSQLParseNode * pCondition = pNode->getChild(1); + if ( pCondition ) // no where clause + { + // now we have to chech the other conditions + // first make the logical easier + ::connectivity::OSQLParseNode::negateSearchCondition(pCondition); + ::connectivity::OSQLParseNode *pNodeTmp = pNode->getChild(1); + + ::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp); + pNodeTmp = pNode->getChild(1); + ::connectivity::OSQLParseNode::absorptions(pNodeTmp); + pNodeTmp = pNode->getChild(1); + // compress sort the criteria @see http://www.openoffice.org/issues/show_bug.cgi?id=24079 + OSQLParseNode::compress(pNodeTmp); + pNodeTmp = pNode->getChild(1); + + // first extract the inner joins conditions + GetInnerJoinCriteria(_pView,pNodeTmp); + // now simplify again, join are checked in ComparisonPredicate + ::connectivity::OSQLParseNode::absorptions(pNodeTmp); + pNodeTmp = pNode->getChild(1); + + // it could happen that pCondition is not more valid + eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pNodeTmp, rLevel); + } + return eErrorCode; + } + //------------------------------------------------------------------------------ + SqlParseError GetANDCriteria( OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode * pCondition, + sal_uInt16& nLevel, + sal_Bool bHaving, + bool bAddOrOnOneLine); + //------------------------------------------------------------------------------ + SqlParseError ComparisonPredicate(OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode * pCondition, + const sal_uInt16 nLevel, + sal_Bool bHaving, + bool bAddOrOnOneLine); + //------------------------------------------------------------------------------ + SqlParseError GetORCriteria(OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode * pCondition, + sal_uInt16& nLevel , + sal_Bool bHaving, + bool bAddOrOnOneLine) + { + SqlParseError eErrorCode = eOk; + + // Runde Klammern um den Ausdruck + if (pCondition->count() == 3 && + SQL_ISPUNCTUATION(pCondition->getChild(0),"(") && + SQL_ISPUNCTUATION(pCondition->getChild(2),")")) + { + eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pCondition->getChild(1),nLevel,bHaving,bAddOrOnOneLine); + } + // oder Verknuepfung + // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term + else if (SQL_ISRULE(pCondition,search_condition)) + { + for (int i = 0; i < 3 && eErrorCode == eOk ; i+=2) + { + const ::connectivity::OSQLParseNode* pChild = pCondition->getChild(i); + if ( SQL_ISRULE(pChild,search_condition) ) + eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pChild,nLevel,bHaving,bAddOrOnOneLine); + else + { + eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pChild, nLevel,bHaving, i == 0 ? false : bAddOrOnOneLine); + if ( !bAddOrOnOneLine) + nLevel++; + } + } + } + else + eErrorCode = GetANDCriteria( _pView,_pSelectionBrw,pCondition, nLevel, bHaving,bAddOrOnOneLine ); + + return eErrorCode; + } + //-------------------------------------------------------------------------------------------------- + bool CheckOrCriteria(const ::connectivity::OSQLParseNode* _pCondition,::connectivity::OSQLParseNode* _pFirstColumnRef) + { + bool bRet = true; + ::connectivity::OSQLParseNode* pFirstColumnRef = _pFirstColumnRef; + for (int i = 0; i < 3 && bRet; i+=2) + { + const ::connectivity::OSQLParseNode* pChild = _pCondition->getChild(i); + if ( SQL_ISRULE(pChild,search_condition) ) + bRet = CheckOrCriteria(pChild,pFirstColumnRef); + else + { + // this is a simple way to test columns are the same, may be we have to adjust this algo a little bit in future. :-) + ::connectivity::OSQLParseNode* pSecondColumnRef = pChild->getByRule(::connectivity::OSQLParseNode::column_ref); + if ( pFirstColumnRef && pSecondColumnRef ) + bRet = *pFirstColumnRef == *pSecondColumnRef; + else if ( !pFirstColumnRef ) + pFirstColumnRef = pSecondColumnRef; + } + } + return bRet; + } + //-------------------------------------------------------------------------------------------------- + SqlParseError GetANDCriteria( OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode * pCondition, + sal_uInt16& nLevel, + sal_Bool bHaving, + bool bAddOrOnOneLine) + { + const ::com::sun::star::lang::Locale aLocale = _pView->getLocale(); + const ::rtl::OUString sDecimal = _pView->getDecimalSeparator(); + + // ich werde ein paar Mal einen gecasteten Pointer auf meinen ::com::sun::star::sdbcx::Container brauchen + OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); + SqlParseError eErrorCode = eOk; + + // Runde Klammern + if (SQL_ISRULE(pCondition,boolean_primary)) + { + // check if we have to put the or criteria on one line. + const ::connectivity::OSQLParseNode* pSearchCondition = pCondition->getChild(1); + bool bMustAddOrOnOneLine = CheckOrCriteria(pSearchCondition,NULL); + if ( SQL_ISRULE( pSearchCondition, search_condition) ) // we have a or + { + _pSelectionBrw->DuplicateConditionLevel( nLevel); + eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition->getChild(0), nLevel,bHaving,bMustAddOrOnOneLine ); + ++nLevel; + eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition->getChild(2), nLevel,bHaving,bMustAddOrOnOneLine ); + } + else + eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition, nLevel,bHaving,bMustAddOrOnOneLine ); + } + // Das erste Element ist (wieder) eine AND-Verknuepfung + else if ( SQL_ISRULE(pCondition,boolean_term) ) + { + OSL_ENSURE(pCondition->count() == 3,"Illegal definifiton of boolean_term"); + eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(0), nLevel,bHaving,bAddOrOnOneLine ); + if ( eErrorCode == eOk ) + eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(2), nLevel,bHaving,bAddOrOnOneLine ); + } + else if (SQL_ISRULE( pCondition, comparison_predicate)) + { + eErrorCode = ComparisonPredicate(_pView,_pSelectionBrw,pCondition,nLevel,bHaving,bAddOrOnOneLine); + } + else if( SQL_ISRULE(pCondition,like_predicate) ) + { + const ::connectivity::OSQLParseNode* pValueExp = pCondition->getChild(0); + if (SQL_ISRULE(pValueExp, column_ref ) ) + { + ::rtl::OUString aColumnName; + ::rtl::OUString aCondition; + Reference< XConnection> xConnection = rController.getConnection(); + if ( xConnection.is() ) + { + Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + // the international doesn't matter I have a string + pCondition->parseNodeToPredicateStr(aCondition, + xConnection, + rController.getNumberFormatter(), + aLocale, + static_cast<sal_Char>(sDecimal.toChar()), + &rController.getParser().getContext()); + + pValueExp->parseNodeToPredicateStr( aColumnName, + xConnection, + rController.getNumberFormatter(), + aLocale, + static_cast<sal_Char>(sDecimal.toChar()), + &rController.getParser().getContext()); + + // don't display the column name + aCondition = aCondition.copy(aColumnName.getLength()); + aCondition = aCondition.trim(); + } + + OTableFieldDescRef aDragLeft = new OTableFieldDesc(); + if ( eOk == ( eErrorCode = FillDragInfo(_pView,pValueExp,aDragLeft) )) + { + if ( bHaving ) + aDragLeft->SetGroupBy(sal_True); + _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine); + } + } + else if(SQL_ISRULEOR2(pValueExp,general_set_fct ,set_fct_spec) || + SQL_ISRULEOR2(pValueExp,position_exp,extract_exp) || + SQL_ISRULEOR2(pValueExp,fold,char_substring_fct) || + SQL_ISRULEOR2(pValueExp,length_exp,char_value_fct)) + { + AddFunctionCondition( _pView, + _pSelectionBrw, + pCondition, + nLevel, + bHaving, + bAddOrOnOneLine); + } + else + { + eErrorCode = eNoColumnInLike; + String sError(ModuleRes(STR_QRY_LIKE_LEFT_NO_COLUMN)); + _pView->getController().appendError( sError ); + } + } + else if( SQL_ISRULEOR2(pCondition,test_for_null,in_predicate) + || SQL_ISRULEOR2(pCondition,all_or_any_predicate,between_predicate)) + { + if ( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) ) + { + AddFunctionCondition( _pView, + _pSelectionBrw, + pCondition, + nLevel, + bHaving, + bAddOrOnOneLine); + } + else if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) ) + { + // parse condition + ::rtl::OUString sCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,1); + OTableFieldDescRef aDragLeft = new OTableFieldDesc(); + if ( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) ) + { + if ( bHaving ) + aDragLeft->SetGroupBy(sal_True); + _pSelectionBrw->AddCondition(aDragLeft, sCondition, nLevel,bAddOrOnOneLine); + } + } + else + { + // Funktions-Bedingung parsen + ::rtl::OUString sCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,1); + Reference< XConnection> xConnection = rController.getConnection(); + Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + // the international doesn't matter I have a string + ::rtl::OUString sName; + pCondition->getChild(0)->parseNodeToPredicateStr(sName, + xConnection, + rController.getNumberFormatter(), + aLocale, + static_cast<sal_Char>(sDecimal.toChar()), + &rController.getParser().getContext()); + + OTableFieldDescRef aDragLeft = new OTableFieldDesc(); + aDragLeft->SetField(sName); + aDragLeft->SetFunctionType(FKT_OTHER); + + if ( bHaving ) + aDragLeft->SetGroupBy(sal_True); + _pSelectionBrw->AddCondition(aDragLeft, sCondition, nLevel,bAddOrOnOneLine); + } + } + else if( SQL_ISRULEOR2(pCondition,existence_test,unique_test) ) + { + // Funktions-Bedingung parsen + ::rtl::OUString aCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,0); + + OTableFieldDescRef aDragLeft = new OTableFieldDesc(); + aDragLeft->SetField(aCondition); + aDragLeft->SetFunctionType(FKT_CONDITION); + + eErrorCode = _pSelectionBrw->InsertField(aDragLeft,BROWSER_INVALIDID,sal_False,sal_True).is() ? eOk : eTooManyColumns; + } + else //! TODO not supported yet + eErrorCode = eStatementTooComplex; + // Fehler einfach weiterreichen. + return eErrorCode; + } + //------------------------------------------------------------------------------ + SqlParseError AddFunctionCondition(OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode * pCondition, + const sal_uInt16 nLevel, + sal_Bool bHaving, + bool bAddOrOnOneLine) + { + SqlParseError eErrorCode = eOk; + OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); + + OSQLParseNode* pFunction = pCondition->getChild(0); + + OSL_ENSURE(SQL_ISRULEOR2(pFunction,general_set_fct ,set_fct_spec) || + SQL_ISRULEOR2(pFunction,position_exp,extract_exp) || + SQL_ISRULEOR2(pFunction,fold,char_substring_fct) || + SQL_ISRULEOR2(pFunction,length_exp,char_value_fct),"Illegal call!"); + ::rtl::OUString aCondition; + OTableFieldDescRef aDragLeft = new OTableFieldDesc(); + + ::rtl::OUString aColumnName; + Reference< XConnection> xConnection = rController.getConnection(); + if(xConnection.is()) + { + Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + pCondition->parseNodeToPredicateStr(aCondition, + xConnection, + rController.getNumberFormatter(), + _pView->getLocale(), + static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()), + &rController.getParser().getContext()); + + pFunction->parseNodeToStr( aColumnName, + xConnection, + &rController.getParser().getContext(), + sal_True, + sal_True); // quote is to true because we need quoted elements inside the function + // don't display the column name + aCondition = aCondition.copy(aColumnName.getLength()); + aCondition = aCondition.trim(); + if ( aCondition.indexOf('=',0) == 0 ) // ignore the equal sign + aCondition = aCondition.copy(1); + + + if ( SQL_ISRULE(pFunction, general_set_fct ) ) + { + sal_Int32 nFunctionType = FKT_AGGREGATE; + OSQLParseNode* pParamNode = pFunction->getChild(pFunction->count()-2); + if ( pParamNode && pParamNode->getTokenValue().toChar() == '*' ) + { + OJoinTableView::OTableWindowMap* pTabList = _pView->getTableView()->GetTabWinMap(); + OJoinTableView::OTableWindowMap::iterator aIter = pTabList->begin(); + OJoinTableView::OTableWindowMap::iterator aTabEnd = pTabList->end(); + for(;aIter != aTabEnd;++aIter) + { + OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second); + if (pTabWin->ExistsField( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), aDragLeft )) + { + aDragLeft->SetAlias(String()); + aDragLeft->SetTable(String()); + break; + } + } + } + else if( eOk != ( eErrorCode = FillDragInfo(_pView,pParamNode,aDragLeft)) + && SQL_ISRULE(pParamNode,num_value_exp) ) + { + ::rtl::OUString sParameterValue; + pParamNode->parseNodeToStr( sParameterValue, + xConnection, + &rController.getParser().getContext()); + nFunctionType |= FKT_NUMERIC; + aDragLeft->SetField(sParameterValue); + eErrorCode = eOk; + } + aDragLeft->SetFunctionType(nFunctionType); + if ( bHaving ) + aDragLeft->SetGroupBy(sal_True); + sal_Int32 nIndex = 0; + aDragLeft->SetFunction(aColumnName.getToken(0,'(',nIndex)); + } + else + { + // bei unbekannten Funktionen wird der gesamte Text in das Field gechrieben + aDragLeft->SetField(aColumnName); + if(bHaving) + aDragLeft->SetGroupBy(sal_True); + aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC); + } + _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine); + } + + return eErrorCode; + } + //------------------------------------------------------------------------------ + SqlParseError ComparisonPredicate(OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode * pCondition, + const sal_uInt16 nLevel, + sal_Bool bHaving + ,bool bAddOrOnOneLine) + { + SqlParseError eErrorCode = eOk; + OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); + + DBG_ASSERT(SQL_ISRULE( pCondition, comparison_predicate),"ComparisonPredicate: pCondition ist kein ComparisonPredicate"); + if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) + || SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref) ) + { + ::rtl::OUString aCondition; + OTableFieldDescRef aDragLeft = new OTableFieldDesc(); + + if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) && SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) ) + { + OTableFieldDescRef aDragRight = new OTableFieldDesc(); + if (eOk != ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) || + eOk != ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(2),aDragRight))) + return eErrorCode; + + OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>( + _pView->getTableView()->GetTabConn(static_cast<OQueryTableWindow*>(aDragLeft->GetTabWindow()), + static_cast<OQueryTableWindow*>(aDragRight->GetTabWindow()), + true)); + if ( pConn ) + { + OConnectionLineDataVec* pLineDataList = pConn->GetData()->GetConnLineDataList(); + OConnectionLineDataVec::iterator aIter = pLineDataList->begin(); + OConnectionLineDataVec::iterator aEnd = pLineDataList->end(); + for(;aIter != aEnd;++aIter) + { + if((*aIter)->GetSourceFieldName() == aDragLeft->GetField() || + (*aIter)->GetDestFieldName() == aDragLeft->GetField() ) + break; + } + if(aIter != aEnd) + return eOk; + } + } + + sal_uInt32 nPos = 0; + if(SQL_ISRULE(pCondition->getChild(0), column_ref )) + { + nPos = 0; + sal_uInt32 i=1; + + // don't display the equal + if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL) + i++; + + // Bedingung parsen + aCondition = ParseCondition(rController + ,pCondition + ,_pView->getDecimalSeparator() + ,_pView->getLocale() + ,i); + } + else if( SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) ) + { + nPos = pCondition->count()-1; + + sal_Int32 i = static_cast<sal_Int32>(pCondition->count() - 2); + switch (pCondition->getChild(i)->getNodeType()) + { + case SQL_NODE_EQUAL: + // don't display the equal + i--; + break; + case SQL_NODE_LESS: + // take the opposite as we change the order + i--; + aCondition = aCondition + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">")); + break; + case SQL_NODE_LESSEQ: + // take the opposite as we change the order + i--; + aCondition = aCondition + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">=")); + break; + case SQL_NODE_GREAT: + // take the opposite as we change the order + i--; + aCondition = aCondition + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<")); + break; + case SQL_NODE_GREATEQ: + // take the opposite as we change the order + i--; + aCondition = aCondition + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<=")); + break; + default: + break; + } + + // go backward + Reference< XConnection> xConnection = rController.getConnection(); + if(xConnection.is()) + { + Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + for (; i >= 0; i--) + pCondition->getChild(i)->parseNodeToPredicateStr(aCondition, + xConnection, + rController.getNumberFormatter(), + _pView->getLocale(), + static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()), + &rController.getParser().getContext()); + } + } + // else ??? + + + if( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(nPos),aDragLeft))) + { + if(bHaving) + aDragLeft->SetGroupBy(sal_True); + _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine); + } + } + else if( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) ) + { + AddFunctionCondition( _pView, + _pSelectionBrw, + pCondition, + nLevel, + bHaving, + bAddOrOnOneLine); + } + else // kann sich nur um einen Expr. Ausdruck handeln + { + ::rtl::OUString aName,aCondition; + + ::connectivity::OSQLParseNode *pLhs = pCondition->getChild(0); + ::connectivity::OSQLParseNode *pRhs = pCondition->getChild(2); + // Feldnamen + Reference< XConnection> xConnection = rController.getConnection(); + if(xConnection.is()) + { + pLhs->parseNodeToStr(aName, + xConnection, + &rController.getParser().getContext(), + sal_True); + // Kriterium + aCondition = pCondition->getChild(1)->getTokenValue(); + pRhs->parseNodeToPredicateStr(aCondition, + xConnection, + rController.getNumberFormatter(), + _pView->getLocale(), + static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()), + &rController.getParser().getContext()); + } + + OTableFieldDescRef aDragLeft = new OTableFieldDesc(); + aDragLeft->SetField(aName); + aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC); + // und anh"angen + _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine); + } + return eErrorCode; + } + + //------------------------------------------------------------------------------ + namespace + { + OQueryTableWindow* lcl_findColumnInTables( const ::rtl::OUString& _rColumName, const OJoinTableView::OTableWindowMap& _rTabList, OTableFieldDescRef& _rInfo ) + { + OJoinTableView::OTableWindowMap::const_iterator aIter = _rTabList.begin(); + OJoinTableView::OTableWindowMap::const_iterator aEnd = _rTabList.end(); + for ( ; aIter != aEnd; ++aIter ) + { + OQueryTableWindow* pTabWin = static_cast< OQueryTableWindow* >( aIter->second ); + if ( pTabWin && pTabWin->ExistsField( _rColumName, _rInfo ) ) + return pTabWin; + } + return NULL; + } + } + + //------------------------------------------------------------------------------ + void InsertColumnRef(const OQueryDesignView* _pView, + const ::connectivity::OSQLParseNode * pColumnRef, + ::rtl::OUString& aColumnName, + const ::rtl::OUString& aColumnAlias, + ::rtl::OUString& aTableRange, + OTableFieldDescRef& _raInfo, + OJoinTableView::OTableWindowMap* pTabList) + { + + // Tabellennamen zusammen setzen + ::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator(); + rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange ); + + sal_Bool bFound(sal_False); + DBG_ASSERT(aColumnName.getLength(),"Columnname darf nicht leer sein"); + if (!aTableRange.getLength()) + { + // SELECT column, ... + bFound = NULL != lcl_findColumnInTables( aColumnName, *pTabList, _raInfo ); + if ( bFound && ( aColumnName.toChar() != '*' ) ) + _raInfo->SetFieldAlias(aColumnAlias); + } + else + { + // SELECT range.column, ... + OQueryTableWindow* pTabWin = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable(aTableRange); + + if (pTabWin && pTabWin->ExistsField(aColumnName, _raInfo)) + { + if(aColumnName.toChar() != '*') + _raInfo->SetFieldAlias(aColumnAlias); + bFound = sal_True; + } + } + if (!bFound) + { + _raInfo->SetTable(::rtl::OUString()); + _raInfo->SetAlias(::rtl::OUString()); + _raInfo->SetField(aColumnName); + _raInfo->SetFieldAlias(aColumnAlias); // nyi : hier ein fortlaufendes Expr_1, Expr_2 ... + _raInfo->SetFunctionType(FKT_OTHER); + } + } + //----------------------------------------------------------------------------- + sal_Bool checkJoinConditions( const OQueryDesignView* _pView, + const ::connectivity::OSQLParseNode* _pNode ) + { + const ::connectivity::OSQLParseNode* pJoinNode = NULL; + sal_Bool bRet = sal_True; + if (SQL_ISRULE(_pNode,qualified_join)) + pJoinNode = _pNode; + else if (SQL_ISRULE(_pNode,table_ref) + && _pNode->count() == 3 + && SQL_ISPUNCTUATION(_pNode->getChild(0),"(") + && SQL_ISPUNCTUATION(_pNode->getChild(2),")") ) // '(' joined_table ')' + pJoinNode = _pNode->getChild(1); + else if (! ( SQL_ISRULE(_pNode, table_ref) && _pNode->count() == 2) ) // table_node table_primary_as_range_column + bRet = sal_False; + + if (pJoinNode && !InsertJoin(_pView,pJoinNode)) + bRet = sal_False; + return bRet; + } + //----------------------------------------------------------------------------- + sal_Bool InsertJoin(const OQueryDesignView* _pView, + const ::connectivity::OSQLParseNode *pNode) + { + DBG_ASSERT( SQL_ISRULE( pNode, qualified_join ) || SQL_ISRULE( pNode, joined_table ) || SQL_ISRULE( pNode, cross_union ), + "OQueryDesignView::InsertJoin: Fehler im Parse Tree"); + + if (SQL_ISRULE(pNode,joined_table)) + return InsertJoin(_pView,pNode->getChild(1)); + + // first check the left and right side + const ::connectivity::OSQLParseNode* pRightTableRef = pNode->getChild(3); // table_ref + if ( SQL_ISRULE(pNode, qualified_join) && SQL_ISTOKEN(pNode->getChild(1),NATURAL) ) + pRightTableRef = pNode->getChild(4); // table_ref + + if ( !checkJoinConditions(_pView,pNode->getChild(0)) || !checkJoinConditions(_pView,pRightTableRef)) + return sal_False; + + // named column join wird später vieleicht noch implementiert + // SQL_ISRULE(pNode->getChild(4),named_columns_join) + EJoinType eJoinType = INNER_JOIN; + bool bNatural = false; + if ( SQL_ISRULE(pNode, qualified_join) ) + { + ::connectivity::OSQLParseNode* pJoinType = pNode->getChild(1); // join_type + if ( SQL_ISTOKEN(pJoinType,NATURAL) ) + { + bNatural = true; + pJoinType = pNode->getChild(2); + } + + if (SQL_ISRULE(pJoinType,join_type) && SQL_ISTOKEN(pJoinType->getChild(0),INNER)) + { + eJoinType = INNER_JOIN; + } + else + { + if (SQL_ISRULE(pJoinType,join_type)) // eine Ebene tiefer + pJoinType = pJoinType->getChild(0); + + if (SQL_ISTOKEN(pJoinType->getChild(0),LEFT)) + eJoinType = LEFT_JOIN; + else if(SQL_ISTOKEN(pJoinType->getChild(0),RIGHT)) + eJoinType = RIGHT_JOIN; + else + eJoinType = FULL_JOIN; + } + if ( SQL_ISRULE(pNode->getChild(4),join_condition) ) + { + if ( InsertJoinConnection(_pView,pNode->getChild(4)->getChild(1), eJoinType,pNode->getChild(0),pRightTableRef) != eOk ) + return sal_False; + } + } + else if ( SQL_ISRULE(pNode, cross_union) ) + { + eJoinType = CROSS_JOIN; + pRightTableRef = pNode->getChild(pNode->count() - 1); + } + else + return sal_False; + + if ( eJoinType == CROSS_JOIN || bNatural ) + { + + OQueryTableWindow* pLeftWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pNode->getChild(0)) ); + OQueryTableWindow* pRightWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pRightTableRef) ); + OSL_ENSURE(pLeftWindow && pRightWindow,"Table Windows could not be found!"); + if ( !pLeftWindow || !pRightWindow ) + return sal_False; + + OTableFieldDescRef aDragLeft = new OTableFieldDesc(); + aDragLeft->SetTabWindow(pLeftWindow); + aDragLeft->SetTable(pLeftWindow->GetTableName()); + aDragLeft->SetAlias(pLeftWindow->GetAliasName()); + + OTableFieldDescRef aDragRight = new OTableFieldDesc(); + aDragRight->SetTabWindow(pRightWindow); + aDragRight->SetTable(pRightWindow->GetTableName()); + aDragRight->SetAlias(pRightWindow->GetAliasName()); + + insertConnection(_pView,eJoinType,aDragLeft,aDragRight,bNatural); + } + + + return sal_True; + } + //------------------------------------------------------------------------------ + void insertUnUsedFields(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw) + { + // now we have to insert the fields which aren't in the statement + OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); + OTableFields& rUnUsedFields = rController.getUnUsedFields(); + OTableFields::iterator aEnd = rUnUsedFields.end(); + for(OTableFields::iterator aIter = rUnUsedFields.begin();aIter != aEnd;++aIter) + if(_pSelectionBrw->InsertField(*aIter,BROWSER_INVALIDID,sal_False,sal_False).is()) + (*aIter) = NULL; + OTableFields().swap( rUnUsedFields ); + } + + //------------------------------------------------------------------------------ + SqlParseError InitFromParseNodeImpl(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw) + { + SqlParseError eErrorCode = eOk; + + OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); + + _pSelectionBrw->PreFill(); + _pSelectionBrw->SetReadOnly(rController.isReadOnly()); + _pSelectionBrw->Fill(); + + + ::connectivity::OSQLParseTreeIterator& aIterator = rController.getParseIterator(); + const ::connectivity::OSQLParseNode* pParseTree = aIterator.getParseTree(); + + do + { + if ( !pParseTree ) + { + // now we have to insert the fields which aren't in the statement + insertUnUsedFields(_pView,_pSelectionBrw); + break; + } + + if ( !rController.isEsacpeProcessing() ) // not allowed in this mode + { + eErrorCode = eNativeMode; + break; + } + + if ( !( SQL_ISRULE( pParseTree, select_statement ) ) ) + { + eErrorCode = eNoSelectStatement; + break; + } + + Reference< XConnection> xConnection = rController.getConnection(); + if ( !xConnection.is() ) + { + DBG_ERROR( "InitFromParseNodeImpl: no connection? no connection!" ); + break; + } + + const OSQLTables& aMap = aIterator.getTables(); + ::comphelper::UStringMixLess aTmp(aMap.key_comp()); + ::comphelper::UStringMixEqual aKeyComp( aTmp.isCaseSensitive() ); + + Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + try + { + sal_Int32 nMax = xMetaData->getMaxTablesInSelect(); + if ( nMax && nMax < (sal_Int32)aMap.size() ) + { + eErrorCode = eTooManyTables; + break; + } + + ::rtl::OUString sComposedName; + ::rtl::OUString aQualifierName; + ::rtl::OUString sAlias; + + OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView()); + pTableView->clearLayoutInformation(); + OSQLTables::const_iterator aIter = aMap.begin(); + OSQLTables::const_iterator aEnd = aMap.end(); + for(;aIter != aEnd;++aIter) + { + OSQLTable xTable = aIter->second; + Reference< XPropertySet > xTableProps( xTable, UNO_QUERY_THROW ); + + sAlias = aIter->first; + + // check whether this is a query + Reference< XPropertySetInfo > xPSI = xTableProps->getPropertySetInfo(); + bool bIsQuery = xPSI.is() && xPSI->hasPropertyByName( PROPERTY_COMMAND ); + + if ( bIsQuery ) + OSL_VERIFY( xTableProps->getPropertyValue( PROPERTY_NAME ) >>= sComposedName ); + else + { + sComposedName = ::dbtools::composeTableName( xMetaData, xTableProps, ::dbtools::eInDataManipulation, false, false, false ); + + // if the alias is the complete (composed) table, then shorten it + if ( aKeyComp( sComposedName, aIter->first ) ) + { + ::rtl::OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents( xMetaData, sComposedName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation ); + sAlias = sTable; + } + } + + // find the existent window for this alias + OQueryTableWindow* pExistentWin = pTableView->FindTable( sAlias ); + if ( !pExistentWin ) + { + pTableView->AddTabWin( sComposedName, sAlias, sal_False ); // don't create data here + } + else + { + // there already exists a window for this alias .... + if ( !aKeyComp( pExistentWin->GetData()->GetComposedName(), sComposedName ) ) + // ... but for another complete table name -> new window + pTableView->AddTabWin(sComposedName, sAlias); + } + } + + // now delete the data for which we haven't any tablewindow + OJoinTableView::OTableWindowMap aTableMap(*pTableView->GetTabWinMap()); + OJoinTableView::OTableWindowMap::iterator aIterTableMap = aTableMap.begin(); + OJoinTableView::OTableWindowMap::iterator aIterTableEnd = aTableMap.end(); + for(;aIterTableMap != aIterTableEnd;++aIterTableMap) + { + if(aMap.find(aIterTableMap->second->GetComposedName()) == aMap.end() && + aMap.find(aIterTableMap->first) == aMap.end()) + pTableView->RemoveTabWin(aIterTableMap->second); + } + + if ( eOk == (eErrorCode = FillOuterJoins(_pView,pParseTree->getChild(3)->getChild(0)->getChild(1))) ) + { + // check if we have a distinct statement + if(SQL_ISTOKEN(pParseTree->getChild(1),DISTINCT)) + { + rController.setDistinct(sal_True); + rController.InvalidateFeature(SID_QUERY_DISTINCT_VALUES); + } + if ( (eErrorCode = InstallFields(_pView,pParseTree, pTableView->GetTabWinMap())) == eOk ) + { + // GetSelectionCriteria must be called before GetHavingCriteria + sal_uInt16 nLevel=0; + + if ( eOk == (eErrorCode = GetSelectionCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) ) + { + if ( eOk == (eErrorCode = GetGroupCriteria(_pView,_pSelectionBrw,pParseTree)) ) + { + if ( eOk == (eErrorCode = GetHavingCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) ) + { + if ( eOk == (eErrorCode = GetOrderCriteria(_pView,_pSelectionBrw,pParseTree)) ) + insertUnUsedFields(_pView,_pSelectionBrw); + } + } + } + } + } + } + catch(SQLException&) + { + OSL_ASSERT(!"getMaxTablesInSelect!"); + } + } + while ( false ); + + // Durch das Neuerzeugen wurden wieder Undo-Actions in den Manager gestellt + rController.getUndoMgr()->Clear(); + _pSelectionBrw->Invalidate(); + return eErrorCode; + } + //------------------------------------------------------------------------------ + /** fillSelectSubList + @return + <TRUE/> when columns could be inserted otherwise <FALSE/> + */ + //------------------------------------------------------------------------------ + SqlParseError fillSelectSubList( OQueryDesignView* _pView, + OJoinTableView::OTableWindowMap* _pTabList) + { + SqlParseError eErrorCode = eOk; + sal_Bool bFirstField = sal_True; + ::rtl::OUString sAsterix(RTL_CONSTASCII_USTRINGPARAM("*")); + OJoinTableView::OTableWindowMap::iterator aIter = _pTabList->begin(); + OJoinTableView::OTableWindowMap::iterator aEnd = _pTabList->end(); + for(;aIter != aEnd && eOk == eErrorCode ;++aIter) + { + OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second); + OTableFieldDescRef aInfo = new OTableFieldDesc(); + if (pTabWin->ExistsField( sAsterix, aInfo )) + { + eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField); + bFirstField = sal_False; + } + } + return eErrorCode; + } + //------------------------------------------------------------------------------ + SqlParseError InstallFields(OQueryDesignView* _pView, + const ::connectivity::OSQLParseNode* pNode, + OJoinTableView::OTableWindowMap* pTabList ) + { + if( pNode==0 || !SQL_ISRULE(pNode,select_statement)) + return eNoSelectStatement; + + ::connectivity::OSQLParseNode* pParseTree = pNode->getChild(2); // selection + sal_Bool bFirstField = sal_True; // bei der Initialisierung muß auf alle Faelle das erste Feld neu aktiviert werden + + SqlParseError eErrorCode = eOk; + + if ( pParseTree->isRule() && SQL_ISPUNCTUATION(pParseTree->getChild(0),"*") ) + { + // SELECT * ... + eErrorCode = fillSelectSubList(_pView,pTabList); + } + else if (SQL_ISRULE(pParseTree,scalar_exp_commalist) ) + { + // SELECT column, ... + OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); + Reference< XConnection> xConnection = rController.getConnection(); + + ::rtl::OUString aColumnName,aTableRange; + for (sal_uInt32 i = 0; i < pParseTree->count() && eOk == eErrorCode ; ++i) + { + ::connectivity::OSQLParseNode * pColumnRef = pParseTree->getChild(i); + + do { + + if ( SQL_ISRULE(pColumnRef,select_sublist) ) + { + eErrorCode = fillSelectSubList(_pView,pTabList); + break; + } + + if ( SQL_ISRULE(pColumnRef,derived_column) ) + { + ::rtl::OUString aColumnAlias(rController.getParseIterator().getColumnAlias(pColumnRef)); // kann leer sein + pColumnRef = pColumnRef->getChild(0); + OTableFieldDescRef aInfo = new OTableFieldDesc(); + + if ( pColumnRef->count() == 3 && + SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") && + SQL_ISPUNCTUATION(pColumnRef->getChild(2),")") + ) + pColumnRef = pColumnRef->getChild(1); + + if (SQL_ISRULE(pColumnRef,column_ref)) + { + InsertColumnRef(_pView,pColumnRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList); + eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField); + bFirstField = sal_False; + } + else if(SQL_ISRULEOR2(pColumnRef,general_set_fct ,set_fct_spec) || + SQL_ISRULEOR2(pColumnRef,position_exp,extract_exp) || + SQL_ISRULEOR2(pColumnRef,fold,char_substring_fct) || + SQL_ISRULEOR2(pColumnRef,length_exp,char_value_fct)) + { + ::rtl::OUString aColumns; + pColumnRef->parseNodeToPredicateStr(aColumns, + xConnection, + rController.getNumberFormatter(), + _pView->getLocale(), + static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()), + &rController.getParser().getContext()); + + sal_Int32 nFunctionType = FKT_NONE; + ::connectivity::OSQLParseNode* pParamRef = NULL; + sal_Int32 nColumnRefPos = pColumnRef->count() - 2; + if ( nColumnRefPos >= 0 && static_cast<sal_uInt32>(nColumnRefPos) < pColumnRef->count() ) + pParamRef = pColumnRef->getChild(nColumnRefPos); + + if ( SQL_ISRULE(pColumnRef,general_set_fct) + && SQL_ISRULE(pParamRef,column_ref) ) + { + // Parameter auf Columnref pr"ufen + InsertColumnRef(_pView,pParamRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList); + } + else if ( SQL_ISRULE(pColumnRef,general_set_fct) ) + { + if ( pParamRef && pParamRef->getTokenValue().toChar() == '*' ) + { + OJoinTableView::OTableWindowMap::iterator aIter = pTabList->begin(); + OJoinTableView::OTableWindowMap::iterator aEnd = pTabList->end(); + for(;aIter != aEnd;++aIter) + { + OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second); + if (pTabWin->ExistsField( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), aInfo )) + { + aInfo->SetAlias(String()); + aInfo->SetTable(String()); + break; + } + } + } + else + { + ::rtl::OUString sFieldName = aColumns; + if ( pParamRef ) + { // we got an aggregate function but without column name inside + // so we set the whole argument of the function as field name + nFunctionType |= FKT_NUMERIC; + sFieldName = ::rtl::OUString(); + pParamRef->parseNodeToStr( sFieldName, + xConnection, + &rController.getParser().getContext(), + sal_True, + sal_True); // quote is to true because we need quoted elements inside the function + } + aInfo->SetDataType(DataType::DOUBLE); + aInfo->SetFieldType(TAB_NORMAL_FIELD); + aInfo->SetField(sFieldName); + } + aInfo->SetTabWindow(NULL); + aInfo->SetFieldAlias(aColumnAlias); + } + else + { + _pView->fillFunctionInfo(pColumnRef,aColumns,aInfo); + aInfo->SetFieldAlias(aColumnAlias); + } + + if ( SQL_ISRULE(pColumnRef,general_set_fct) ) + { + aInfo->SetFunctionType(nFunctionType|FKT_AGGREGATE); + String aCol(aColumns); + aInfo->SetFunction(aCol.GetToken(0,'(').EraseTrailingChars(' ')); + } + else + aInfo->SetFunctionType(nFunctionType|FKT_OTHER); + + eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField); + bFirstField = sal_False; + } + else + { + ::rtl::OUString aColumns; + pColumnRef->parseNodeToStr( aColumns, + xConnection, + &rController.getParser().getContext(), + sal_True, + sal_True); // quote is to true because we need quoted elements inside the function + + aInfo->SetTabWindow( NULL ); + + // since we support queries in queries, the thingie might belong to an existing "table" + OQueryTableWindow* pExistingTable = lcl_findColumnInTables( aColumns, *pTabList, aInfo ); + if ( pExistingTable ) + { + aInfo->SetTabWindow( pExistingTable ); + aInfo->SetTable( pExistingTable->GetTableName() ); + aInfo->SetAlias( pExistingTable->GetAliasName() ); + } + + aInfo->SetDataType(DataType::DOUBLE); + aInfo->SetFieldType(TAB_NORMAL_FIELD); + aInfo->SetField(aColumns); + aInfo->SetFieldAlias(aColumnAlias); + aInfo->SetFunctionType(FKT_NUMERIC | FKT_OTHER); + + eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField); + bFirstField = sal_False; + } + + break; + } + + DBG_ERROR( "InstallFields: don't know how to interpret this parse node!" ); + + } while ( false ); + } + } + else + eErrorCode = eStatementTooComplex; + + return eErrorCode; + } + //------------------------------------------------------------------------------ + SqlParseError GetOrderCriteria( OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode* pParseRoot ) + { + SqlParseError eErrorCode = eOk; + if (!pParseRoot->getChild(3)->getChild(4)->isLeaf()) + { + ::connectivity::OSQLParseNode* pNode = pParseRoot->getChild(3)->getChild(4)->getChild(2); + ::connectivity::OSQLParseNode* pParamRef = NULL; + + OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); + EOrderDir eOrderDir; + OTableFieldDescRef aDragLeft = new OTableFieldDesc(); + for( sal_uInt32 i=0 ; i<pNode->count() ; i++ ) + { + eOrderDir = ORDER_ASC; + ::connectivity::OSQLParseNode* pChild = pNode->getChild( i ); + + if (SQL_ISTOKEN( pChild->getChild(1), DESC ) ) + eOrderDir = ORDER_DESC; + + ::connectivity::OSQLParseNode* pArgument = pChild->getChild(0); + + if(SQL_ISRULE(pArgument,column_ref)) + { + if( eOk == FillDragInfo(_pView,pArgument,aDragLeft)) + _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i); + else // it could be a alias name for a field + { + ::rtl::OUString aTableRange,aColumnName; + ::connectivity::OSQLParseTreeIterator& rParseIter = rController.getParseIterator(); + rParseIter.getColumnRange( pArgument, aColumnName, aTableRange ); + + OTableFields& aList = rController.getTableFieldDesc(); + OTableFields::iterator aIter = aList.begin(); + OTableFields::iterator aEnd = aList.end(); + for(;aIter != aEnd;++aIter) + { + OTableFieldDescRef pEntry = *aIter; + if(pEntry.is() && pEntry->GetFieldAlias() == aColumnName) + pEntry->SetOrderDir( eOrderDir ); + } + } + } + else if(SQL_ISRULE(pArgument, general_set_fct ) && + SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) && + eOk == FillDragInfo(_pView,pParamRef,aDragLeft)) + _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i ); + else if( SQL_ISRULE(pArgument, set_fct_spec ) ) + { + + Reference< XConnection> xConnection = rController.getConnection(); + if(xConnection.is()) + { + ::rtl::OUString sCondition; + pArgument->parseNodeToPredicateStr(sCondition, + xConnection, + rController.getNumberFormatter(), + _pView->getLocale(), + static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()), + &rController.getParser().getContext()); + _pView->fillFunctionInfo(pArgument,sCondition,aDragLeft); + aDragLeft->SetFunctionType(FKT_OTHER); + aDragLeft->SetOrderDir(eOrderDir); + aDragLeft->SetVisible(sal_False); + _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i ); + } + else + eErrorCode = eColumnNotFound; + } + else + eErrorCode = eColumnNotFound; + } + } + return eErrorCode; + } + //------------------------------------------------------------------------------ + SqlParseError GetHavingCriteria( OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode* pSelectRoot, + sal_uInt16& rLevel ) + { + SqlParseError eErrorCode = eOk; + if (!pSelectRoot->getChild(3)->getChild(3)->isLeaf()) + eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSelectRoot->getChild(3)->getChild(3)->getChild(1),rLevel, sal_True); + return eErrorCode; + } + //------------------------------------------------------------------------------ + SqlParseError GetGroupCriteria( OQueryDesignView* _pView, + OSelectionBrowseBox* _pSelectionBrw, + const ::connectivity::OSQLParseNode* pSelectRoot ) + { + SqlParseError eErrorCode = eOk; + if (!pSelectRoot->getChild(3)->getChild(2)->isLeaf()) // opt_group_by_clause + { + OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); + ::connectivity::OSQLParseNode* pGroupBy = pSelectRoot->getChild(3)->getChild(2)->getChild(2); + OTableFieldDescRef aDragInfo = new OTableFieldDesc(); + for( sal_uInt32 i=0 ; i < pGroupBy->count() && eOk == eErrorCode; ++i ) + { + ::connectivity::OSQLParseNode* pParamRef = NULL; + ::connectivity::OSQLParseNode* pArgument = pGroupBy->getChild( i ); + if(SQL_ISRULE(pArgument,column_ref)) + { + if ( eOk == (eErrorCode = FillDragInfo(_pView,pArgument,aDragInfo)) ) + { + aDragInfo->SetGroupBy(sal_True); + _pSelectionBrw->AddGroupBy(aDragInfo,i); + } + } + else if(SQL_ISRULE(pArgument, general_set_fct ) && + SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) && + eOk == FillDragInfo(_pView,pParamRef,aDragInfo)) + { + aDragInfo->SetGroupBy(sal_True); + _pSelectionBrw->AddGroupBy( aDragInfo, i ); + } + else if( SQL_ISRULE(pArgument, set_fct_spec ) ) + { + Reference< XConnection> xConnection = rController.getConnection(); + if(xConnection.is()) + { + ::rtl::OUString sGroupByExpression; + pArgument->parseNodeToStr( sGroupByExpression, + xConnection, + &rController.getParser().getContext(), + sal_True, + sal_True); // quote is to true because we need quoted elements inside the function + _pView->fillFunctionInfo(pArgument,sGroupByExpression,aDragInfo); + aDragInfo->SetFunctionType(FKT_OTHER); + aDragInfo->SetGroupBy(sal_True); + aDragInfo->SetVisible(sal_False); + _pSelectionBrw->AddGroupBy( aDragInfo, i ); + } + else + eErrorCode = eColumnNotFound; + } + } + } + return eErrorCode; + } + + //------------------------------------------------------------------------------ + String getParseErrorMessage( SqlParseError _eErrorCode ) + { + USHORT nResId; + switch(_eErrorCode) + { + case eIllegalJoin: + nResId = STR_QRY_ILLEGAL_JOIN; + break; + case eStatementTooLong: + nResId = STR_QRY_TOO_LONG_STATEMENT; + break; + case eNoConnection: + nResId = STR_QRY_SYNTAX; + break; + case eNoSelectStatement: + nResId = STR_QRY_NOSELECT; + break; + case eColumnInLikeNotFound: + nResId = STR_QRY_SYNTAX; + break; + case eNoColumnInLike: + nResId = STR_QRY_SYNTAX; + break; + case eColumnNotFound: + nResId = STR_QRY_SYNTAX; + break; + case eNativeMode: + nResId = STR_QRY_NATIVE; + break; + case eTooManyTables: + nResId = STR_QRY_TOO_MANY_TABLES; + break; + case eTooManyConditions: + nResId = STR_QRY_TOOMANYCOND; + break; + case eTooManyColumns: + nResId = STR_QRY_TOO_MANY_COLUMNS; + break; + case eStatementTooComplex: + nResId = STR_QRY_TOOCOMPLEX; + break; + default: + nResId = STR_QRY_SYNTAX; + break; + } + ; + return String( ModuleRes( nResId ) ); + } + + //------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ +} +// end of anonymouse namespace +DBG_NAME(OQueryDesignView) + +OQueryDesignView::OQueryDesignView( OQueryContainerWindow* _pParent, + OQueryController& _rController, + const Reference< XMultiServiceFactory >& _rFactory) + :OQueryView( _pParent, _rController, _rFactory ) + ,m_aSplitter( this ) + ,m_eChildFocus(NONE) + ,m_bInKeyEvent(sal_False) + ,m_bInSplitHandler( sal_False ) +{ + DBG_CTOR(OQueryDesignView,NULL); + + try + { + SvtSysLocale aSysLocale; + m_aLocale = aSysLocale.GetLocaleData().getLocale(); + m_sDecimalSep = aSysLocale.GetLocaleData().getNumDecimalSep(); + } + catch(Exception&) + { + } + + m_pSelectionBox = new OSelectionBrowseBox(this); + + setNoneVisbleRow(static_cast<OQueryController&>(getController()).getVisibleRows()); + m_pSelectionBox->Show(); + // Splitter einrichten + m_aSplitter.SetSplitHdl(LINK(this, OQueryDesignView,SplitHdl)); + m_aSplitter.Show(); + +} +// ----------------------------------------------------------------------------- +OQueryDesignView::~OQueryDesignView() +{ + if ( m_pTableView ) + ::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::RemoveWindow)); + ::std::auto_ptr<Window> aTemp(m_pSelectionBox); + m_pSelectionBox = NULL; + + DBG_DTOR(OQueryDesignView,NULL); +} +//------------------------------------------------------------------------------ +IMPL_LINK( OQueryDesignView, SplitHdl, void*, /*p*/ ) +{ + if (!getController().isReadOnly()) + { + m_bInSplitHandler = sal_True; + m_aSplitter.SetPosPixel( Point( m_aSplitter.GetPosPixel().X(),m_aSplitter.GetSplitPosPixel() ) ); + static_cast<OQueryController&>(getController()).setSplitPos(m_aSplitter.GetSplitPosPixel()); + static_cast<OQueryController&>(getController()).setModified( sal_True ); + Resize(); + m_bInSplitHandler = sal_True; + } + return 0L; +} +// ------------------------------------------------------------------------- +void OQueryDesignView::Construct() +{ + m_pTableView = new OQueryTableView(m_pScrollWindow,this); + ::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::AddWindow)); + OQueryView::Construct(); +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::initialize() +{ + if(static_cast<OQueryController&>(getController()).getSplitPos() != -1) + { + m_aSplitter.SetPosPixel( Point( m_aSplitter.GetPosPixel().X(),static_cast<OQueryController&>(getController()).getSplitPos() ) ); + m_aSplitter.SetSplitPosPixel(static_cast<OQueryController&>(getController()).getSplitPos()); + } + m_pSelectionBox->initialize(); + reset(); +} +// ------------------------------------------------------------------------- +void OQueryDesignView::resizeDocumentView(Rectangle& _rPlayground) +{ + Point aPlaygroundPos( _rPlayground.TopLeft() ); + Size aPlaygroundSize( _rPlayground.GetSize() ); + + // calc the split pos, and forward it to the controller + sal_Int32 nSplitPos = static_cast<OQueryController&>(getController()).getSplitPos(); + if ( 0 != aPlaygroundSize.Height() ) + { + if ( ( -1 == nSplitPos ) + || ( nSplitPos >= aPlaygroundSize.Height() ) + ) + { + // let the selection browse box determine an optimal size + Size aSelectionBoxSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize ); + nSplitPos = aPlaygroundSize.Height() - aSelectionBoxSize.Height() - m_aSplitter.GetSizePixel().Height(); + // still an invalid size? + if ( nSplitPos == -1 || nSplitPos >= aPlaygroundSize.Height() ) + nSplitPos = sal_Int32(aPlaygroundSize.Height()*0.6); + + static_cast<OQueryController&>(getController()).setSplitPos(nSplitPos); + } + + if ( !m_bInSplitHandler ) + { // the resize is triggered by something else than the split handler + // our main focus is to try to preserve the size of the selectionbrowse box + Size aSelBoxSize = m_pSelectionBox->GetSizePixel(); + if ( aSelBoxSize.Height() ) + { + // keep the size of the sel box constant + nSplitPos = aPlaygroundSize.Height() - m_aSplitter.GetSizePixel().Height() - aSelBoxSize.Height(); + + // and if the box is smaller than the optimal size, try to do something about it + Size aSelBoxOptSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize ); + if ( aSelBoxOptSize.Height() > aSelBoxSize.Height() ) + { + nSplitPos = aPlaygroundSize.Height() - m_aSplitter.GetSizePixel().Height() - aSelBoxOptSize.Height(); + } + + static_cast< OQueryController& >(getController()).setSplitPos( nSplitPos ); + } + } + } + + // normalize the split pos + Point aSplitPos = Point( _rPlayground.Left(), nSplitPos ); + Size aSplitSize = Size( _rPlayground.GetSize().Width(), m_aSplitter.GetSizePixel().Height() ); + + if( ( aSplitPos.Y() + aSplitSize.Height() ) > ( aPlaygroundSize.Height() )) + aSplitPos.Y() = aPlaygroundSize.Height() - aSplitSize.Height(); + + if( aSplitPos.Y() <= aPlaygroundPos.Y() ) + aSplitPos.Y() = aPlaygroundPos.Y() + sal_Int32(aPlaygroundSize.Height() * 0.2); + + // position the table + Size aTableViewSize(aPlaygroundSize.Width(), aSplitPos.Y() - aPlaygroundPos.Y()); + m_pScrollWindow->SetPosSizePixel(aPlaygroundPos, aTableViewSize); + + // position the selection browse box + Point aPos( aPlaygroundPos.X(), aSplitPos.Y() + aSplitSize.Height() ); + m_pSelectionBox->SetPosSizePixel( aPos, Size( aPlaygroundSize.Width(), aPlaygroundSize.Height() - aSplitSize.Height() - aTableViewSize.Height() )); + + // set the size of the splitter + m_aSplitter.SetPosSizePixel( aSplitPos, aSplitSize ); + m_aSplitter.SetDragRectPixel( _rPlayground ); + + // just for completeness: there is no space left, we occupied it all ... + _rPlayground.SetPos( _rPlayground.BottomRight() ); + _rPlayground.SetSize( Size( 0, 0 ) ); +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::setReadOnly(sal_Bool _bReadOnly) +{ + m_pSelectionBox->SetReadOnly(_bReadOnly); +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::clear() +{ + m_pSelectionBox->ClearAll(); // clear the whole selection + m_pTableView->ClearAll(); +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::setStatement(const ::rtl::OUString& /*_rsStatement*/) +{ +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::copy() +{ + if( m_eChildFocus == SELECTION) + m_pSelectionBox->copy(); +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryDesignView::isCutAllowed() +{ + sal_Bool bAllowed = sal_False; + if ( SELECTION == m_eChildFocus ) + bAllowed = m_pSelectionBox->isCutAllowed(); + return bAllowed; +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryDesignView::isPasteAllowed() +{ + sal_Bool bAllowed = sal_False; + if ( SELECTION == m_eChildFocus ) + bAllowed = m_pSelectionBox->isPasteAllowed(); + return bAllowed; +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryDesignView::isCopyAllowed() +{ + sal_Bool bAllowed = sal_False; + if ( SELECTION == m_eChildFocus ) + bAllowed = m_pSelectionBox->isCopyAllowed(); + return bAllowed; +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::stopTimer() +{ + m_pSelectionBox->stopTimer(); +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::startTimer() +{ + m_pSelectionBox->startTimer(); +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::cut() +{ + if( m_eChildFocus == SELECTION) + { + m_pSelectionBox->cut(); + static_cast<OQueryController&>(getController()).setModified(sal_True); + } +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::paste() +{ + if( m_eChildFocus == SELECTION) + { + m_pSelectionBox->paste(); + static_cast<OQueryController&>(getController()).setModified(sal_True); + } +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::TableDeleted(const ::rtl::OUString& rAliasName) +{ + // Nachricht, dass Tabelle aus dem Fenster gel"oscht wurde + DeleteFields(rAliasName); + static_cast<OQueryController&>(getController()).InvalidateFeature(ID_BROWSER_ADDTABLE); // view nochmal bescheid sagen +} +//------------------------------------------------------------------------------ +void OQueryDesignView::DeleteFields( const ::rtl::OUString& rAliasName ) +{ + m_pSelectionBox->DeleteFields( rAliasName ); +} +// ----------------------------------------------------------------------------- +bool OQueryDesignView::HasFieldByAliasName(const ::rtl::OUString& rFieldName, OTableFieldDescRef& rInfo) const +{ + return m_pSelectionBox->HasFieldByAliasName( rFieldName, rInfo); +} +// ----------------------------------------------------------------------------- +SqlParseError OQueryDesignView::InsertField( const OTableFieldDescRef& rInfo, sal_Bool bVis, sal_Bool bActivate) +{ + return m_pSelectionBox->InsertField( rInfo, BROWSER_INVALIDID,bVis, bActivate ).is() ? eOk : eTooManyColumns; +} +// ----------------------------------------------------------------------------- +sal_Int32 OQueryDesignView::getColWidth(sal_uInt16 _nColPos) const +{ + static sal_Int32 s_nDefaultWidth = GetTextWidth(String(RTL_CONSTASCII_USTRINGPARAM("0"))) * 15; + sal_Int32 nWidth = static_cast<OQueryController&>(getController()).getColWidth(_nColPos); + if ( !nWidth ) + nWidth = s_nDefaultWidth; + return nWidth; +} +//------------------------------------------------------------------------------ +void OQueryDesignView::fillValidFields(const ::rtl::OUString& sAliasName, ComboBox* pFieldList) +{ + DBG_ASSERT(pFieldList != NULL, "OQueryDesignView::FillValidFields : What the hell do you think I can do with a NULL-ptr ? This will crash !"); + pFieldList->Clear(); + + sal_Bool bAllTables = sAliasName.getLength() == 0; + + OJoinTableView::OTableWindowMap* pTabWins = m_pTableView->GetTabWinMap(); + ::rtl::OUString strCurrentPrefix; + ::std::vector< ::rtl::OUString> aFields; + OJoinTableView::OTableWindowMap::iterator aIter = pTabWins->begin(); + OJoinTableView::OTableWindowMap::iterator aEnd = pTabWins->end(); + for(;aIter != aEnd;++aIter) + { + OQueryTableWindow* pCurrentWin = static_cast<OQueryTableWindow*>(aIter->second); + if (bAllTables || (pCurrentWin->GetAliasName() == sAliasName)) + { + strCurrentPrefix = pCurrentWin->GetAliasName(); + strCurrentPrefix += ::rtl::OUString('.'); + + pCurrentWin->EnumValidFields(aFields); + + ::std::vector< ::rtl::OUString>::iterator aStrIter = aFields.begin(); + ::std::vector< ::rtl::OUString>::iterator aStrEnd = aFields.end(); + for(;aStrIter != aStrEnd;++aStrIter) + { + if (bAllTables || aStrIter->toChar() == '*') + pFieldList->InsertEntry(::rtl::OUString(strCurrentPrefix) += *aStrIter); + else + pFieldList->InsertEntry(*aStrIter); + } + + if (!bAllTables) + // das heisst, dass ich in diesen Block kam, weil der Tabellenname genau der gesuchte war, also bin ich fertig + // (dadurch verhindere ich auch das doppelte Einfuegen von Feldern, wenn eine Tabelle mehrmals als TabWin vorkommt) + break; + } + } +} +// ----------------------------------------------------------------------------- +long OQueryDesignView::PreNotify(NotifyEvent& rNEvt) +{ + switch (rNEvt.GetType()) + { + case EVENT_GETFOCUS: +#if OSL_DEBUG_LEVEL > 0 + { + Window* pFocus = Application::GetFocusWindow(); + (void)pFocus; + } +#endif + + if ( m_pSelectionBox && m_pSelectionBox->HasChildPathFocus() ) + m_eChildFocus = SELECTION; + else + m_eChildFocus = TABLEVIEW; + break; + } + + return OQueryView::PreNotify(rNEvt); +} +//------------------------------------------------------------------------------ + + +// ----------------------------------------------------------------------------- +// check if the statement is correct when not returning false +sal_Bool OQueryDesignView::checkStatement() +{ + sal_Bool bRet = sal_True; + if ( m_pSelectionBox ) + bRet = m_pSelectionBox->Save(); // an error occurred so we return no + return bRet; +} +//------------------------------------------------------------------------------- +::rtl::OUString OQueryDesignView::getStatement() +{ + OQueryController& rController = static_cast<OQueryController&>(getController()); + m_rController.clearError(); + // used for fields which aren't any longer in the statement + OTableFields& rUnUsedFields = rController.getUnUsedFields(); + OTableFields().swap( rUnUsedFields ); + + // create the select columns + sal_uInt32 nFieldcount = 0; + OTableFields& rFieldList = rController.getTableFieldDesc(); + OTableFields::iterator aIter = rFieldList.begin(); + OTableFields::iterator aEnd = rFieldList.end(); + for(;aIter != aEnd;++aIter) + { + OTableFieldDescRef pEntryField = *aIter; + if ( pEntryField->GetField().getLength() && pEntryField->IsVisible() ) + ++nFieldcount; + else if (pEntryField->GetField().getLength() && + !pEntryField->HasCriteria() && + pEntryField->isNoneFunction() && + pEntryField->GetOrderDir() == ORDER_NONE && + !pEntryField->IsGroupBy() && + !pEntryField->GetFunction().getLength() ) + rUnUsedFields.push_back(pEntryField); + } + if ( !nFieldcount ) // keine Felder sichtbar also zur"uck + { + rUnUsedFields = rFieldList; + return ::rtl::OUString(); + } + + OQueryTableView::OTableWindowMap* pTabList = m_pTableView->GetTabWinMap(); + sal_uInt32 nTabcount = pTabList->size(); + + ::rtl::OUString aFieldListStr(GenerateSelectList(this,rFieldList,nTabcount>1)); + if( !aFieldListStr.getLength() ) + return ::rtl::OUString(); + // Ausnahmebehandlung, wenn keine Felder angegeben worden sind + // Dann darf die Tabpage nicht gewechselt werden + // Im TabBarSelectHdl wird der SQL-::rtl::OUString auf STATEMENT_NOFIELDS abgefragt + // und eine Errormeldung erzeugt + // ----------------- Tabellenliste aufbauen ---------------------- + + const ::std::vector<OTableConnection*>* pConnList = m_pTableView->getTableConnections(); + Reference< XConnection> xConnection = rController.getConnection(); + ::rtl::OUString aTableListStr(GenerateFromClause(xConnection,pTabList,pConnList)); + DBG_ASSERT(aTableListStr.getLength(), "OQueryDesignView::getStatement() : unerwartet : habe Felder, aber keine Tabellen !"); + // wenn es Felder gibt, koennen die nur durch Einfuegen aus einer schon existenten Tabelle entstanden sein; wenn andererseits + // eine Tabelle geloescht wird, verschwinden auch die zugehoerigen Felder -> ergo KANN es das nicht geben, dass Felder + // existieren, aber keine Tabellen (und aFieldListStr hat schon eine Laenge, das stelle ich oben sicher) + ::rtl::OUStringBuffer aHavingStr,aCriteriaListStr; + // ----------------- Kriterien aufbauen ---------------------- + if (!GenerateCriterias(this,aCriteriaListStr,aHavingStr,rFieldList, nTabcount > 1)) + return ::rtl::OUString(); + + ::rtl::OUString aJoinCrit; + GenerateInnerJoinCriterias(xConnection,aJoinCrit,pConnList); + if(aJoinCrit.getLength()) + { + ::rtl::OUString aTmp(RTL_CONSTASCII_USTRINGPARAM("( ")); + aTmp += aJoinCrit; + aTmp += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" )")); + if(aCriteriaListStr.getLength()) + { + aTmp += C_AND; + aTmp += aCriteriaListStr.makeStringAndClear(); + } + aCriteriaListStr = aTmp; + } + // ----------------- Statement aufbauen ---------------------- + ::rtl::OUStringBuffer aSqlCmd(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT "))); + if(static_cast<OQueryController&>(getController()).isDistinct()) + aSqlCmd.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DISTINCT "))); + aSqlCmd.append(aFieldListStr); + aSqlCmd.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM "))); + aSqlCmd.append(aTableListStr); + + if (aCriteriaListStr.getLength()) + { + aSqlCmd.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE "))); + aSqlCmd.append(aCriteriaListStr.makeStringAndClear()); + } + // ----------------- GroupBy aufbauen und Anh"angen ------------ + Reference<XDatabaseMetaData> xMeta; + if ( xConnection.is() ) + xMeta = xConnection->getMetaData(); + sal_Bool bUseAlias = nTabcount > 1; + if ( xMeta.is() ) + bUseAlias = bUseAlias || !xMeta->supportsGroupByUnrelated(); + + aSqlCmd.append(GenerateGroupBy(this,rFieldList,bUseAlias)); + // ----------------- having Anh"angen ------------ + if(aHavingStr.getLength()) + { + aSqlCmd.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" HAVING "))); + aSqlCmd.append(aHavingStr.makeStringAndClear()); + } + // ----------------- Sortierung aufbauen und Anh"angen ------------ + ::rtl::OUString sOrder; + SqlParseError eErrorCode = eOk; + if ( (eErrorCode = GenerateOrder(this,rFieldList,nTabcount > 1,sOrder)) == eOk) + aSqlCmd.append(sOrder); + else + { + if ( !m_rController.hasError() ) + m_rController.appendError( getParseErrorMessage( eErrorCode ) ); + + m_rController.displayError(); + } + + ::rtl::OUString sSQL = aSqlCmd.makeStringAndClear(); + if ( xConnection.is() ) + { + ::connectivity::OSQLParser& rParser( rController.getParser() ); + ::rtl::OUString sErrorMessage; + ::std::auto_ptr<OSQLParseNode> pParseNode( rParser.parseTree( sErrorMessage, sSQL, sal_True ) ); + if ( pParseNode.get() ) + { + OSQLParseNode* pNode = pParseNode->getChild(3)->getChild(1); + if ( pNode->count() > 1 ) + { + ::connectivity::OSQLParseNode * pCondition = pNode->getChild(1); + if ( pCondition ) // no where clause + { + OSQLParseNode::compress(pCondition); + ::rtl::OUString sTemp; + pParseNode->parseNodeToStr(sTemp,xConnection); + sSQL = sTemp; + } + } + } + } + return sSQL; +} +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +void OQueryDesignView::setSlotEnabled(sal_Int32 _nSlotId,sal_Bool _bEnable) +{ + sal_uInt16 nRow; + switch (_nSlotId) + { + case SID_QUERY_VIEW_FUNCTIONS: + nRow = BROW_FUNCTION_ROW; + break; + case SID_QUERY_VIEW_TABLES: + nRow = BROW_TABLE_ROW; + break; + case SID_QUERY_VIEW_ALIASES: + nRow = BROW_COLUMNALIAS_ROW; + break; + default: + // ???????????? + nRow = 0; + break; + } + m_pSelectionBox->SetRowVisible(nRow,_bEnable); + m_pSelectionBox->Invalidate(); +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryDesignView::isSlotEnabled(sal_Int32 _nSlotId) +{ + sal_uInt16 nRow; + switch (_nSlotId) + { + case SID_QUERY_VIEW_FUNCTIONS: + nRow = BROW_FUNCTION_ROW; + break; + case SID_QUERY_VIEW_TABLES: + nRow = BROW_TABLE_ROW; + break; + case SID_QUERY_VIEW_ALIASES: + nRow = BROW_COLUMNALIAS_ROW; + break; + default: + // ????????? + nRow = 0; + break; + } + return m_pSelectionBox->IsRowVisible(nRow); +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::SaveUIConfig() +{ + OQueryController& rCtrl = static_cast<OQueryController&>(getController()); + rCtrl.SaveTabWinsPosSize( m_pTableView->GetTabWinMap(), m_pScrollWindow->GetHScrollBar()->GetThumbPos(), m_pScrollWindow->GetVScrollBar()->GetThumbPos() ); + rCtrl.setVisibleRows( m_pSelectionBox->GetNoneVisibleRows() ); + if ( m_aSplitter.GetSplitPosPixel() != 0 ) + rCtrl.setSplitPos( m_aSplitter.GetSplitPosPixel() ); +} +// ----------------------------------------------------------------------------- +OSQLParseNode* OQueryDesignView::getPredicateTreeFromEntry(OTableFieldDescRef pEntry, + const String& _sCriteria, + ::rtl::OUString& _rsErrorMessage, + Reference<XPropertySet>& _rxColumn) const +{ + OSL_ENSURE(pEntry.is(),"Entry is null!"); + if(!pEntry.is()) + return NULL; + Reference< XConnection> xConnection = static_cast<OQueryController&>(getController()).getConnection(); + if(!xConnection.is()) + return NULL; + + ::connectivity::OSQLParser& rParser( static_cast<OQueryController&>(getController()).getParser() ); + OQueryTableWindow* pWin = static_cast<OQueryTableWindow*>(pEntry->GetTabWindow()); + + String sTest(_sCriteria); + // special handling for functions + if ( pEntry->GetFunctionType() & (FKT_OTHER | FKT_AGGREGATE | FKT_NUMERIC) ) + { + // we have a function here so we have to distinguish the type of return value + String sFunction; + if ( pEntry->isNumericOrAggreateFunction() ) + sFunction = pEntry->GetFunction(); + + if ( !sFunction.Len() ) + sFunction = pEntry->GetField(); + + if(sFunction.GetTokenCount('(') > 1) + sFunction = sFunction.GetToken(0,'('); // this should be the name of the function + + sal_Int32 nType = ::connectivity::OSQLParser::getFunctionReturnType(sFunction,&rParser.getContext()); + if ( nType == DataType::OTHER || (!sFunction.Len() && pEntry->isNumericOrAggreateFunction()) ) + { + // first try the international version + ::rtl::OUString sSql; + sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT * ")); + sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM x WHERE ")); + sSql += pEntry->GetField(); + sSql += _sCriteria; + ::std::auto_ptr<OSQLParseNode> pParseNode( rParser.parseTree( _rsErrorMessage, sSql, sal_True ) ); + nType = DataType::DOUBLE; + if ( pParseNode.get() ) + { + OSQLParseNode* pColumnRef = pParseNode->getByRule(OSQLParseNode::column_ref); + if ( pColumnRef ) + { + OTableFieldDescRef aField = new OTableFieldDesc(); + if ( eOk == FillDragInfo(this,pColumnRef,aField) ) + { + nType = aField->GetDataType(); + } + } + } + } + + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + parse::OParseColumn* pColumn = new parse::OParseColumn( pEntry->GetField(), + ::rtl::OUString(), + ::rtl::OUString(), + ::rtl::OUString(), + ColumnValue::NULLABLE_UNKNOWN, + 0, + 0, + nType, + sal_False, + sal_False, + xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers()); + _rxColumn = pColumn; + pColumn->setFunction(sal_True); + pColumn->setRealName(pEntry->GetField()); + } + else + { + if (pWin) + { + Reference<XNameAccess> xColumns = pWin->GetOriginalColumns(); + if (xColumns.is() && xColumns->hasByName(pEntry->GetField())) + xColumns->getByName(pEntry->GetField()) >>= _rxColumn; + } + } + + OSQLParseNode* pParseNode = rParser.predicateTree( _rsErrorMessage, + sTest, + static_cast<OQueryController&>(getController()).getNumberFormatter(), + _rxColumn); + return pParseNode; +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::GetFocus() +{ + OQueryView::GetFocus(); + if ( m_pSelectionBox && !m_pSelectionBox->HasChildPathFocus() ) + { + // first we have to deactivate the current cell to refill when nescessary + m_pSelectionBox->DeactivateCell(); + m_pSelectionBox->ActivateCell(m_pSelectionBox->GetCurRow(), m_pSelectionBox->GetCurColumnId()); + m_pSelectionBox->GrabFocus(); + } +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::reset() +{ + m_pTableView->ClearAll(); + m_pTableView->ReSync(); +} +// ----------------------------------------------------------------------------- +void OQueryDesignView::setNoneVisbleRow(sal_Int32 _nRows) +{ + m_pSelectionBox->SetNoneVisbleRow(_nRows); +} + +// ----------------------------------------------------------------------------- +void OQueryDesignView::initByFieldDescriptions( const Sequence< PropertyValue >& i_rFieldDescriptions ) +{ + OQueryController& rController = static_cast< OQueryController& >( getController() ); + + m_pSelectionBox->PreFill(); + m_pSelectionBox->SetReadOnly( rController.isReadOnly() ); + m_pSelectionBox->Fill(); + + for ( const PropertyValue* field = i_rFieldDescriptions.getConstArray(); + field != i_rFieldDescriptions.getConstArray() + i_rFieldDescriptions.getLength(); + ++field + ) + { + ::rtl::Reference< OTableFieldDesc > pField( new OTableFieldDesc() ); + pField->Load( *field, true ); + InsertField( pField, sal_True, sal_False ); + } + + rController.getUndoMgr()->Clear(); + m_pSelectionBox->Invalidate(); +} + +// ----------------------------------------------------------------------------- +bool OQueryDesignView::initByParseIterator( ::dbtools::SQLExceptionInfo* _pErrorInfo ) +{ + SqlParseError eErrorCode = eNativeMode; + m_rController.clearError(); + + try + { + eErrorCode = InitFromParseNodeImpl( this, m_pSelectionBox ); + + if ( eErrorCode != eOk ) + { + if ( !m_rController.hasError() ) + m_rController.appendError( getParseErrorMessage( eErrorCode ) ); + + if ( _pErrorInfo ) + { + *_pErrorInfo = m_rController.getError(); + } + else + { + m_rController.displayError(); + } + } + } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return eErrorCode == eOk; +} +//------------------------------------------------------------------------------ +void OQueryDesignView::fillFunctionInfo( const ::connectivity::OSQLParseNode* pNode + ,const ::rtl::OUString& sFunctionTerm + ,OTableFieldDescRef& aInfo) +{ + // get the type out of the funtion name + OQueryController& rController = static_cast<OQueryController&>(getController()); + sal_Int32 nDataType = DataType::DOUBLE; + ::rtl::OUString sFieldName = sFunctionTerm; + OSQLParseNode* pFunctionName = pNode->getChild(0); + if ( !SQL_ISPUNCTUATION(pFunctionName,"{") ) + { + if ( SQL_ISRULEOR2(pNode,length_exp,char_value_fct) ) + pFunctionName = pFunctionName->getChild(0); + + ::rtl::OUString sFunctionName = pFunctionName->getTokenValue(); + if ( !sFunctionName.getLength() ) + sFunctionName = ::rtl::OStringToOUString(OSQLParser::TokenIDToStr(pFunctionName->getTokenID()),RTL_TEXTENCODING_UTF8); + + nDataType = OSQLParser::getFunctionReturnType( + sFunctionName + ,&rController.getParser().getContext()); + } + aInfo->SetDataType(nDataType); + aInfo->SetFieldType(TAB_NORMAL_FIELD); + aInfo->SetField(sFieldName); + aInfo->SetTabWindow(NULL); +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.cxx b/dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.cxx new file mode 100644 index 000000000000..fb662a8b7438 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.cxx @@ -0,0 +1,52 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "QueryMoveTabWinUndoAct.hxx" +#include "JoinTableView.hxx" +#include "QTableWindow.hxx" +using namespace dbaui; +//------------------------------------------------------------------------------ +void OJoinMoveTabWinUndoAct::TogglePosition() +{ + Point ptFrameScrollPos(m_pOwner->GetHScrollBar()->GetThumbPos(), m_pOwner->GetVScrollBar()->GetThumbPos()); + Point ptNext = m_pTabWin->GetPosPixel() + ptFrameScrollPos; + + m_pTabWin->SetPosPixel(m_ptNextPosition - ptFrameScrollPos); + // sieht so aus, als wenn das ptFrameScrollPos sinnlos ist, da ich es hier abziehe und auf das ptNext aufaddiere, wo + // ich es das naechste Mal ja wieder abziehe ... Aber ptFrameScrollPos kann sich natuerlich beim naechsten Mal schon wieder + // geaendert haben ... + m_pOwner->EnsureVisible(m_pTabWin); + + m_ptNextPosition = ptNext; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.hxx b/dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.hxx new file mode 100644 index 000000000000..692bd3946fda --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.hxx @@ -0,0 +1,68 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_OQUERYMOVETABWINUNDOACT_HXX +#define DBAUI_OQUERYMOVETABWINUNDOACT_HXX + +#include "QueryDesignUndoAction.hxx" +#include "dbu_qry.hrc" +#include <tools/gen.hxx> + +namespace dbaui +{ + + // ================================================================================================ + // OQueryMoveTabWinUndoAct - Undo-Klasse fuer Verschieben eines TabWins + class OQueryTableWindow; + class OTableWindow; + class OJoinMoveTabWinUndoAct : public OQueryDesignUndoAction + { + Point m_ptNextPosition; + OTableWindow* m_pTabWin; + + protected: + void TogglePosition(); + + public: + OJoinMoveTabWinUndoAct(OJoinTableView* pOwner, const Point& ptOriginalPosition, OTableWindow* pTabWin); + + virtual void Undo() { TogglePosition(); } + virtual void Redo() { TogglePosition(); } + }; + + // ------------------------------------------------------------------------------------------------ + inline OJoinMoveTabWinUndoAct::OJoinMoveTabWinUndoAct(OJoinTableView* pOwner, const Point& ptOriginalPosition, OTableWindow* pTabWin) + :OQueryDesignUndoAction(pOwner, STR_QUERY_UNDO_MOVETABWIN) + ,m_ptNextPosition(ptOriginalPosition) + ,m_pTabWin(pTabWin) + { + } +} +#endif // DBAUI_OQUERYMOVETABWINUNDOACT_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QuerySizeTabWinUndoAct.hxx b/dbaccess/source/ui/querydesign/QuerySizeTabWinUndoAct.hxx new file mode 100644 index 000000000000..11a2fc0412de --- /dev/null +++ b/dbaccess/source/ui/querydesign/QuerySizeTabWinUndoAct.hxx @@ -0,0 +1,86 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QUERYSIZETABWINUNDOACT_HXX +#define DBAUI_QUERYSIZETABWINUNDOACT_HXX + +#include "QueryDesignUndoAction.hxx" +#include "dbu_qry.hrc" + +namespace dbaui +{ + + // ================================================================================================ + // OQuerySizeTabWinUndoAct - Undo-Klasse fuer Groessenveraenderung eines TabWins + class OTableWindow; + class OJoinSizeTabWinUndoAct : public OQueryDesignUndoAction + { + Point m_ptNextPosition; + Size m_szNextSize; + OTableWindow* m_pTabWin; + + protected: + inline void ToggleSizePosition(); + + public: + OJoinSizeTabWinUndoAct(OJoinTableView* pOwner, const Point& ptOriginalPos, const Size& szOriginalSize, OTableWindow* pTabWin); + // Nebenbedingung : es darf nicht gescrollt worden sein, waehrend die neue Groesse/Position ermittelt wurde, das heisst, die Position + // hier sind physische, nicht logische Koordinaten + // (im Gegensatz zur QueryMoveTabWinUndoAct) + + virtual void Undo() { ToggleSizePosition(); } + virtual void Redo() { ToggleSizePosition(); } + }; + + //------------------------------------------------------------------------------ + inline OJoinSizeTabWinUndoAct::OJoinSizeTabWinUndoAct(OJoinTableView* pOwner, const Point& ptOriginalPos, const Size& szOriginalSize, OTableWindow* pTabWin) + :OQueryDesignUndoAction(pOwner, STR_QUERY_UNDO_SIZETABWIN) + ,m_ptNextPosition(ptOriginalPos) + ,m_szNextSize(szOriginalSize) + ,m_pTabWin(pTabWin) + { + } + + //------------------------------------------------------------------------------ + inline void OJoinSizeTabWinUndoAct::ToggleSizePosition() + { + Point ptNext = m_pTabWin->GetPosPixel(); + Size szNext = m_pTabWin->GetSizePixel(); + + m_pOwner->Invalidate(INVALIDATE_NOCHILDREN); + m_pTabWin->SetPosSizePixel(m_ptNextPosition, m_szNextSize); + m_pOwner->Invalidate(INVALIDATE_NOCHILDREN); + + m_ptNextPosition = ptNext; + m_szNextSize = szNext; + } +} + +#endif //DBAUI_QUERYSIZETABWINUNDOACT_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryTabConnUndoAction.cxx b/dbaccess/source/ui/querydesign/QueryTabConnUndoAction.cxx new file mode 100644 index 000000000000..93775a1be43e --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryTabConnUndoAction.cxx @@ -0,0 +1,139 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "QueryTabConnUndoAction.hxx" +#include "QTableConnection.hxx" +#include <tools/debug.hxx> +#include "QueryTableView.hxx" +#include "QueryAddTabConnUndoAction.hxx" +#include "QueryTabWinShowUndoAct.hxx" +#include "dbu_qry.hrc" + +using namespace dbaui; + +DBG_NAME(OQueryTabConnUndoAction) +// ------------------------------------------------------------------------------------------------ +OQueryTabConnUndoAction::~OQueryTabConnUndoAction() +{ + DBG_DTOR(OQueryTabConnUndoAction,NULL); + if (m_bOwnerOfConn) + { // ich besitze die Connection -> loeschen + m_pOwner->DeselectConn(m_pConnection); + delete m_pConnection; + } +} + +// ------------------------------------------------------------------------------------------------ +OQueryTabConnUndoAction::OQueryTabConnUndoAction(OQueryTableView* pOwner, USHORT nCommentID) + :OQueryDesignUndoAction(pOwner, nCommentID) + ,m_pConnection(NULL) + ,m_bOwnerOfConn(FALSE) +{ + DBG_CTOR(OQueryTabConnUndoAction,NULL); +} +// ----------------------------------------------------------------------------- +OQueryAddTabConnUndoAction::OQueryAddTabConnUndoAction(OQueryTableView* pOwner) + : OQueryTabConnUndoAction(pOwner, STR_QUERY_UNDO_INSERTCONNECTION) +{ +} +// ----------------------------------------------------------------------------- +void OQueryAddTabConnUndoAction::Undo() +{ + static_cast<OQueryTableView*>(m_pOwner)->DropConnection(m_pConnection); + SetOwnership(TRUE); +} +// ----------------------------------------------------------------------------- +void OQueryAddTabConnUndoAction::Redo() +{ + static_cast<OQueryTableView*>(m_pOwner)->GetConnection(m_pConnection); + SetOwnership(FALSE); +} +// ----------------------------------------------------------------------------- +OQueryDelTabConnUndoAction::OQueryDelTabConnUndoAction(OQueryTableView* pOwner) + : OQueryTabConnUndoAction(pOwner, STR_QUERY_UNDO_REMOVECONNECTION) +{ +} +// ----------------------------------------------------------------------------- +void OQueryDelTabConnUndoAction::Undo() +{ + static_cast<OQueryTableView*>(m_pOwner)->GetConnection(m_pConnection); + SetOwnership(FALSE); +} +// ----------------------------------------------------------------------------- +void OQueryDelTabConnUndoAction::Redo() +{ + static_cast<OQueryTableView*>(m_pOwner)->DropConnection(m_pConnection); + SetOwnership(TRUE); +} +// ----------------------------------------------------------------------------- +OQueryTabWinShowUndoAct::OQueryTabWinShowUndoAct(OQueryTableView* pOwner) + : OQueryTabWinUndoAct(pOwner, STR_QUERY_UNDO_TABWINSHOW) +{ +} +// ----------------------------------------------------------------------------- +OQueryTabWinShowUndoAct::~OQueryTabWinShowUndoAct() +{ +} +// ----------------------------------------------------------------------------- +void OQueryTabWinShowUndoAct::Undo() +{ + static_cast<OQueryTableView*>(m_pOwner)->HideTabWin(m_pTabWin, this); + SetOwnership(TRUE); +} +// ----------------------------------------------------------------------------- +void OQueryTabWinShowUndoAct::Redo() +{ + static_cast<OQueryTableView*>(m_pOwner)->ShowTabWin(m_pTabWin, this,sal_True); + SetOwnership(FALSE); +} +// ----------------------------------------------------------------------------- +OQueryTabWinDelUndoAct::OQueryTabWinDelUndoAct(OQueryTableView* pOwner) + : OQueryTabWinUndoAct(pOwner, STR_QUERY_UNDO_TABWINDELETE) +{ +} +// ----------------------------------------------------------------------------- +OQueryTabWinDelUndoAct::~OQueryTabWinDelUndoAct() +{ +} +// ----------------------------------------------------------------------------- +void OQueryTabWinDelUndoAct::Undo() +{ + static_cast<OQueryTableView*>(m_pOwner)->ShowTabWin( m_pTabWin, this,sal_True ); + SetOwnership(FALSE); +} +// ----------------------------------------------------------------------------- +void OQueryTabWinDelUndoAct::Redo() +{ + static_cast<OQueryTableView*>(m_pOwner)->HideTabWin( m_pTabWin, this ); + SetOwnership(TRUE); +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryTabConnUndoAction.hxx b/dbaccess/source/ui/querydesign/QueryTabConnUndoAction.hxx new file mode 100644 index 000000000000..42a2e738bc53 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryTabConnUndoAction.hxx @@ -0,0 +1,59 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QUERYTABCONNUNDOACTION_HXX +#define DBAUI_QUERYTABCONNUNDOACTION_HXX + +#include "QueryDesignUndoAction.hxx" + +namespace dbaui +{ + class OQueryTableConnection; + class OQueryTableView; + class OQueryTabConnUndoAction : public OQueryDesignUndoAction + { + protected: + OQueryTableConnection* m_pConnection; + BOOL m_bOwnerOfConn; + // bin ich alleiniger Eigentuemer der Connection ? (aendert sich mit jedem Redo oder Undo) + + public: + OQueryTabConnUndoAction(OQueryTableView* pOwner, USHORT nCommentID); + virtual ~OQueryTabConnUndoAction(); + + virtual void Undo() = 0; + virtual void Redo() = 0; + + void SetConnection(OQueryTableConnection* pConn) { m_pConnection = pConn; } + // anschliessend bitte SetOwnership + void SetOwnership(BOOL bTakeIt) { m_bOwnerOfConn = bTakeIt; } + }; +} +#endif // DBAUI_QUERYTABCONNUNDOACTION_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryTabWinShowUndoAct.hxx b/dbaccess/source/ui/querydesign/QueryTabWinShowUndoAct.hxx new file mode 100644 index 000000000000..f5988bd65786 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryTabWinShowUndoAct.hxx @@ -0,0 +1,66 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef DBAUI_QUERYTABWINSHOWUNDOACT_HXX +#define DBAUI_QUERYTABWINSHOWUNDOACT_HXX + +#include "QueryTabWinUndoAct.hxx" + +namespace dbaui +{ + // ================================================================================================ + // OQueryTabWinShowUndoAct - Undo-Klasse fuer Anzeigen eines TabWins + + class OQueryTabWinShowUndoAct : public OQueryTabWinUndoAct + { + public: + OQueryTabWinShowUndoAct(OQueryTableView* pOwner); + ~OQueryTabWinShowUndoAct(); + + virtual void Undo(); + virtual void Redo(); + }; + + // ================================================================================================ + // OQueryTabWinDelUndoAct - Undo-Klasse fuer Loeschen eines TabWins + + class OQueryTabWinDelUndoAct : public OQueryTabWinUndoAct + { + public: + OQueryTabWinDelUndoAct(OQueryTableView* pOwner); + ~OQueryTabWinDelUndoAct(); + + virtual void Undo(); + virtual void Redo(); + }; +} +#endif // DBAUI_QUERYTABWINSHOWUNDOACT_HXX + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryTabWinUndoAct.cxx b/dbaccess/source/ui/querydesign/QueryTabWinUndoAct.cxx new file mode 100644 index 000000000000..ff95ed986b25 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryTabWinUndoAct.cxx @@ -0,0 +1,137 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "QueryTabWinUndoAct.hxx" +#include <osl/diagnose.h> +#include "QTableWindow.hxx" +#include "QTableWindowData.hxx" +#include "TableConnection.hxx" +#include "TableConnectionData.hxx" +#include "QueryDesignFieldUndoAct.hxx" +#include "QueryTableView.hxx" + + +using namespace dbaui; +DBG_NAME(OQueryDesignFieldUndoAct) +OQueryDesignFieldUndoAct::OQueryDesignFieldUndoAct(OSelectionBrowseBox* pSelBrwBox, USHORT nCommentID) + : OCommentUndoAction(nCommentID) + , pOwner(pSelBrwBox) + , m_nColumnPostion(BROWSER_INVALIDID) +{ + DBG_CTOR(OQueryDesignFieldUndoAct,NULL); +} +// ----------------------------------------------------------------------------- +OQueryDesignFieldUndoAct::~OQueryDesignFieldUndoAct() +{ + DBG_DTOR(OQueryDesignFieldUndoAct,NULL); + pOwner = NULL; +} +// ----------------------------------------------------------------------------- + +DBG_NAME(OQueryTabWinUndoAct ) +// ------------------------------------------------------------------------------------------------ +OQueryTabWinUndoAct::OQueryTabWinUndoAct(OQueryTableView* pOwner, USHORT nCommentID) + :OQueryDesignUndoAction(pOwner, nCommentID) + ,m_pTabWin(NULL) +{ + DBG_CTOR(OQueryTabWinUndoAct ,NULL); +} +//============================================================================== +OQueryTabWinUndoAct::~OQueryTabWinUndoAct() +{ + DBG_DTOR(OQueryTabWinUndoAct ,NULL); + if (m_bOwnerOfObjects) + { // wenn ich der alleinige Owner des Fenster bin, muss ich dafuer sorgen, dass es geloescht wird + OSL_ENSURE(m_pTabWin != NULL, "OQueryTabWinUndoAct::~OQueryTabWinUndoAct() : m_pTabWin sollte nicht NULL sein"); + OSL_ENSURE(!m_pTabWin->IsVisible(), "OQueryTabWinUndoAct::~OQueryTabWinUndoAct() : *m_pTabWin sollte nicht sichtbar sein"); + + if ( m_pTabWin ) + m_pTabWin->clearListBox(); + delete m_pTabWin; + + // und natuerlich auch die entsprechenden Connections + ::std::vector<OTableConnection*>::iterator aIter = m_vTableConnection.begin(); + ::std::vector<OTableConnection*>::iterator aEnd = m_vTableConnection.end(); + for(;aIter != aEnd;++aIter) + { + m_pOwner->DeselectConn(*aIter); + delete (*aIter); + } + m_vTableConnection.clear(); + } +} +//------------------------------------------------------------------------------ +void OTabFieldCellModifiedUndoAct::Undo() +{ + pOwner->EnterUndoMode(); + OSL_ENSURE(m_nColumnPostion != BROWSER_INVALIDID,"Column position was not set add the undo action!"); + OSL_ENSURE(m_nColumnPostion < pOwner->GetColumnCount(),"Position outside the column count!"); + if ( m_nColumnPostion != BROWSER_INVALIDID ) + { + USHORT nColumnId = pOwner->GetColumnId(m_nColumnPostion); + String strNext = pOwner->GetCellContents(m_nCellIndex, nColumnId); + pOwner->SetCellContents(m_nCellIndex, nColumnId, m_strNextCellContents); + m_strNextCellContents = strNext; + } + pOwner->LeaveUndoMode(); +} + +//------------------------------------------------------------------------------ +void OTabFieldSizedUndoAct::Undo() +{ + pOwner->EnterUndoMode(); + OSL_ENSURE(m_nColumnPostion != BROWSER_INVALIDID,"Column position was not set add the undo action!"); + if ( m_nColumnPostion != BROWSER_INVALIDID ) + { + USHORT nColumnId = pOwner->GetColumnId(m_nColumnPostion); + long nNextWidth = pOwner->GetColumnWidth(nColumnId); + pOwner->SetColWidth(nColumnId, m_nNextWidth); + m_nNextWidth = nNextWidth; + } + pOwner->LeaveUndoMode(); +} +// ----------------------------------------------------------------------------- +void OTabFieldMovedUndoAct::Undo() +{ + pOwner->EnterUndoMode(); + OSL_ENSURE(m_nColumnPostion != BROWSER_INVALIDID,"Column position was not set add the undo action!"); + if ( m_nColumnPostion != BROWSER_INVALIDID ) + { + sal_uInt16 nId = pDescr->GetColumnId(); + USHORT nOldPos = pOwner->GetColumnPos(nId); + pOwner->SetColumnPos(nId,m_nColumnPostion); + pOwner->ColumnMoved(nId,FALSE); + m_nColumnPostion = nOldPos; + } + pOwner->LeaveUndoMode(); +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryTabWinUndoAct.hxx b/dbaccess/source/ui/querydesign/QueryTabWinUndoAct.hxx new file mode 100644 index 000000000000..1fa0df1f3a01 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryTabWinUndoAct.hxx @@ -0,0 +1,87 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QUERYTABWINUNDOACT_HXX +#define DBAUI_QUERYTABWINUNDOACT_HXX + +#include "QueryDesignUndoAction.hxx" +#ifndef INCLUDED_VECTOR +#define INCLUDED_VECTOR +#include <vector> +#endif // INCLUDED_VECTOR + +#include <algorithm> + +namespace dbaui +{ + // ================================================================================================ + // OQueryTabWinUndoAct - Undo-Basisklasse fuer alles, was mit Einfuegen/Entfernen von TabWIns zu tun hat zu tun hat + + class OQueryTableWindow; + class OTableConnection; + class OQueryTableView; + class OQueryTabWinUndoAct : public OQueryDesignUndoAction + { + protected: + ::std::vector<OTableConnection*> m_vTableConnection; + OQueryTableWindow* m_pTabWin; + BOOL m_bOwnerOfObjects; + // bin ich alleiniger Eigentuemer der verwalteten Objekte ? (aendert sich mit jedem Redo oder Undo) + + public: + OQueryTabWinUndoAct(OQueryTableView* pOwner, USHORT nCommentID); + virtual ~OQueryTabWinUndoAct(); + + void SetOwnership(BOOL bTakeIt) { m_bOwnerOfObjects = bTakeIt; } + + + virtual void Undo() = 0; + virtual void Redo() = 0; + + // Zugriff auf das TabWin + void SetTabWin(OQueryTableWindow* pTW) { m_pTabWin = pTW; } + // anschliessend sollte das SetOwnership aufgerufen werden + + // Zugriff auf die verwalteten Connections + USHORT ConnCount() { return (USHORT)m_vTableConnection.size(); } + + ::std::vector<OTableConnection*>* GetTabConnList() { return &m_vTableConnection; } + + void InsertConnection( OTableConnection* pConnection ) { m_vTableConnection.push_back(pConnection); } + void RemoveConnection( OTableConnection* pConnection ) + { + m_vTableConnection.erase(::std::remove(m_vTableConnection.begin(),m_vTableConnection.end(),pConnection),m_vTableConnection.end()); + } + }; + + +} +#endif // DBAUI_QUERYTABWINUNDOACT_HXX + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryTableView.cxx b/dbaccess/source/ui/querydesign/QueryTableView.cxx new file mode 100644 index 000000000000..dcdc0b139c22 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryTableView.cxx @@ -0,0 +1,1036 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "QueryTableView.hxx" +#include "TableFieldInfo.hxx" +#include "TableFieldDescription.hxx" +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include "dbaccess_helpid.hrc" +#include "QTableWindow.hxx" +#include "QTableConnection.hxx" +#include "QTableConnectionData.hxx" +#include "QueryDesignView.hxx" +#include "querycontroller.hxx" +#include "QueryAddTabConnUndoAction.hxx" +#include "QueryTabWinShowUndoAct.hxx" +#include "browserids.hxx" +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include "JAccess.hxx" +#include <com/sun/star/sdbcx/KeyType.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include "dbustrings.hrc" +#include <connectivity/dbtools.hxx> +#include <comphelper/sequence.hxx> +#include "querydlg.hxx" +#include "JoinExchange.hxx" +#include <comphelper/extract.hxx> +#include "QueryDesignView.hxx" +#include "dbu_qry.hrc" +#include <vcl/msgbox.hxx> + +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; +using namespace ::com::sun::star::accessibility; + +//------------------------------------------------------------------------------ +namespace +{ + // ----------------------------------------------------------------------------- + sal_Bool isColumnInKeyType(const Reference<XIndexAccess>& _rxKeys,const ::rtl::OUString& _rColumnName,sal_Int32 _nKeyType) + { + sal_Bool bReturn = sal_False; + if(_rxKeys.is()) + { + Reference<XColumnsSupplier> xColumnsSupplier; + // search the one and only primary key + const sal_Int32 nCount = _rxKeys->getCount(); + for(sal_Int32 i=0;i< nCount;++i) + { + Reference<XPropertySet> xProp(_rxKeys->getByIndex(i),UNO_QUERY); + if(xProp.is()) + { + sal_Int32 nKeyType = 0; + xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType; + if(_nKeyType == nKeyType) + { + xColumnsSupplier.set(xProp,UNO_QUERY); + if(xColumnsSupplier.is()) + { + Reference<XNameAccess> xColumns = xColumnsSupplier->getColumns(); + if(xColumns.is() && xColumns->hasByName(_rColumnName)) + { + bReturn = sal_True; + break; + } + } + } + } + } + } + return bReturn; + } + // ----------------------------------------------------------------------------- + /** appends a new TabAdd Undo action at controller + @param _pView the view which we use + @param _pUndoAction the undo action which should be added + @param _pConnection the connection for which the undo action should be appended + @param _bOwner is the undo action the owner + */ + // ----------------------------------------------------------------------------- + void addUndoAction( OQueryTableView* _pView, + OQueryTabConnUndoAction* _pUndoAction, + OQueryTableConnection* _pConnection, + sal_Bool _bOwner = sal_False) + { + _pUndoAction->SetOwnership(_bOwner); + _pUndoAction->SetConnection(_pConnection); + _pView->getDesignView()->getController().addUndoActionAndInvalidate(_pUndoAction); + } + // ----------------------------------------------------------------------------- + /** openJoinDialog opens the join dialog with this connection data + @param _pView the view which we use + @param _pConnectionData the connection data + + @return true when OK was pressed otherwise false + */ + sal_Bool openJoinDialog(OQueryTableView* _pView,const TTableConnectionData::value_type& _pConnectionData,BOOL _bSelectableTables) + { + OQueryTableConnectionData* pData = static_cast< OQueryTableConnectionData*>(_pConnectionData.get()); + + DlgQryJoin aDlg(_pView,_pConnectionData,_pView->GetTabWinMap(),_pView->getDesignView()->getController().getConnection(),_bSelectableTables); + sal_Bool bOk = aDlg.Execute() == RET_OK; + if( bOk ) + { + pData->SetJoinType(aDlg.GetJoinType()); + _pView->getDesignView()->getController().setModified(sal_True); + } + + return bOk; + } + // ----------------------------------------------------------------------------- + /** connectionModified adds an undo action for the modified connection and forces an redraw + @param _pView the view which we use + @param _pConnection the connection which was modified + @param _bAddUndo true when an undo action should be appended + */ + void connectionModified(OQueryTableView* _pView, + OTableConnection* _pConnection, + sal_Bool _bAddUndo) + { + OSL_ENSURE(_pConnection,"Invalid connection!"); + _pConnection->UpdateLineList(); + + // add an undo action + if ( _bAddUndo ) + addUndoAction( _pView, + new OQueryAddTabConnUndoAction(_pView), + static_cast< OQueryTableConnection*>(_pConnection)); + // redraw + _pConnection->RecalcLines(); + // force an invalidation of the bounding rectangle + _pConnection->InvalidateConnection(); + + _pView->Invalidate(INVALIDATE_NOCHILDREN); + } + // ----------------------------------------------------------------------------- + void addConnections(OQueryTableView* _pView, + const OQueryTableWindow& _rSource, + const OQueryTableWindow& _rDest, + const Reference<XNameAccess>& _rxSourceForeignKeyColumns) + { + if ( _rSource.GetData()->isQuery() || _rDest.GetData()->isQuery() ) + // nothing to do if one of both denotes a query + return; + + // we found a table in our view where we can insert some connections + // the key columns have a property called RelatedColumn + // OQueryTableConnectionData aufbauen + OQueryTableConnectionData* pNewConnData = new OQueryTableConnectionData( _rSource.GetData(), _rDest.GetData() ); + TTableConnectionData::value_type aNewConnData(pNewConnData); + + Reference<XIndexAccess> xReferencedKeys( _rDest.GetData()->getKeys()); + ::rtl::OUString sRelatedColumn; + + // iterate through all foreignkey columns to create the connections + Sequence< ::rtl::OUString> aElements(_rxSourceForeignKeyColumns->getElementNames()); + const ::rtl::OUString* pIter = aElements.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aElements.getLength(); + for(sal_Int32 i=0;pIter != pEnd;++pIter,++i) + { + Reference<XPropertySet> xColumn; + if ( !( _rxSourceForeignKeyColumns->getByName(*pIter) >>= xColumn ) ) + { + OSL_ENSURE( false, "addConnections: invalid foreign key column!" ); + continue; + } + + pNewConnData->SetFieldType(JTCS_FROM,TAB_NORMAL_FIELD); + + xColumn->getPropertyValue(PROPERTY_RELATEDCOLUMN) >>= sRelatedColumn; + pNewConnData->SetFieldType(JTCS_TO,isColumnInKeyType(xReferencedKeys,sRelatedColumn,KeyType::PRIMARY) ? TAB_PRIMARY_FIELD : TAB_NORMAL_FIELD); + + { + Sequence< sal_Int16> aFind(::comphelper::findValue(_rSource.GetOriginalColumns()->getElementNames(),*pIter,sal_True)); + if(aFind.getLength()) + pNewConnData->SetFieldIndex(JTCS_FROM,aFind[0]+1); + else + OSL_ENSURE(0,"Column not found!"); + } + // get the position inside the tabe + Reference<XNameAccess> xRefColumns = _rDest.GetOriginalColumns(); + if(xRefColumns.is()) + { + Sequence< sal_Int16> aFind(::comphelper::findValue(xRefColumns->getElementNames(),sRelatedColumn,sal_True)); + if(aFind.getLength()) + pNewConnData->SetFieldIndex(JTCS_TO,aFind[0]+1); + else + OSL_ENSURE(0,"Column not found!"); + } + pNewConnData->AppendConnLine(*pIter,sRelatedColumn); + + // dann die Conn selber dazu + OQueryTableConnection aNewConn(_pView, aNewConnData); + // der Verweis auf die lokale Variable ist unkritisch, da NotifyQueryTabConn eine neue Kopie anlegt + // und mir hinzufuegen (wenn nicht schon existent) + _pView->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 + } + } +} +//================================================================== +// class OQueryTableView +//================================================================== +DBG_NAME(OQueryTableView) +//------------------------------------------------------------------------ +OQueryTableView::OQueryTableView( Window* pParent,OQueryDesignView* pView) + : OJoinTableView( pParent,pView) +{ + DBG_CTOR(OQueryTableView,NULL); + SetHelpId(HID_CTL_QRYDGNTAB); +} + +//------------------------------------------------------------------------ +OQueryTableView::~OQueryTableView() +{ + DBG_DTOR(OQueryTableView,NULL); +} + +//------------------------------------------------------------------------ +sal_Int32 OQueryTableView::CountTableAlias(const String& rName, sal_Int32& rMax) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + sal_Int32 nRet = 0; + + OTableWindowMapIterator aIter = GetTabWinMap()->find(rName); + while(aIter != GetTabWinMap()->end()) + { + String aNewName; + aNewName = rName; + aNewName += '_'; + aNewName += String::CreateFromInt32(++nRet); + + aIter = GetTabWinMap()->find(aNewName); + } + + rMax = nRet; + + return nRet; +} +//------------------------------------------------------------------------ +void OQueryTableView::ReSync() +{ + DBG_CHKTHIS(OQueryTableView,NULL); + TTableWindowData* pTabWinDataList = m_pView->getController().getTableWindowData(); + DBG_ASSERT((getTableConnections()->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; + + TTableWindowData::reverse_iterator aIter = pTabWinDataList->rbegin(); + // Fenster kreieren und einfuegen + + for(;aIter != pTabWinDataList->rend();++aIter) + { + OQueryTableWindowData* pData = static_cast<OQueryTableWindowData*>(aIter->get()); + OTableWindow* pTabWin = createWindow(*aIter); + + // 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 + pTabWin->clearListBox(); + delete pTabWin; + arrInvalidTables.push_back(pData->GetAliasName()); + + pTabWinDataList->erase( ::std::remove(pTabWinDataList->begin(),pTabWinDataList->end(),*aIter) ,pTabWinDataList->end()); + 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 + TTableConnectionData* pTabConnDataList = m_pView->getController().getTableConnectionData(); + TTableConnectionData::reverse_iterator aConIter = pTabConnDataList->rbegin(); + + for(;aConIter != pTabConnDataList->rend();++aConIter) + { + OQueryTableConnectionData* pTabConnData = static_cast<OQueryTableConnectionData*>(aConIter->get()); + + // gibt es die beiden Tabellen zur Connection ? + String strTabExistenceTest = pTabConnData->getReferencingTable()->GetWinName(); + sal_Bool bInvalid = ::std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end(); + strTabExistenceTest = pTabConnData->getReferencedTable()->GetWinName(); + 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; + } + + // adds a new connection to join view and notifies our accessible and invaldates the controller + addConnection(new OQueryTableConnection(this, *aConIter)); + } +} + +//------------------------------------------------------------------------ +void OQueryTableView::ClearAll() +{ + DBG_CHKTHIS(OQueryTableView,NULL); + OJoinTableView::ClearAll(); + + SetUpdateMode(sal_True); + m_pView->getController().setModified(sal_True); +} + +// ----------------------------------------------------------------------------- +OTableWindow* OQueryTableView::createWindow(const TTableWindowData::value_type& _pData) +{ + return new OQueryTableWindow(this,_pData); +} + +//------------------------------------------------------------------------------ +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; + const ::std::vector<OTableConnection*>* pConnections = getTableConnections(); + ::std::vector<OTableConnection*>::const_iterator aEnd = pConnections->end(); + ::std::vector<OTableConnection*>::const_iterator aIter = ::std::find( pConnections->begin(), + aEnd, + static_cast<const OTableConnection*>(&rNewConn) + ); + if(aIter == aEnd ) + { + aIter = pConnections->begin(); + for(;aIter != aEnd;++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()); + TTableConnectionData::value_type aData(pNewData); + OQueryTableConnection* pNewConn = new OQueryTableConnection(this, aData); + GetConnection(pNewConn); + + connectionModified(this,pNewConn,_bCreateUndoAction); + } +} +// ----------------------------------------------------------------------------- +OTableWindowData* OQueryTableView::CreateImpl(const ::rtl::OUString& _rComposedName + ,const ::rtl::OUString& _sTableName + ,const ::rtl::OUString& _rWinName) +{ + return new OQueryTableWindowData( _rComposedName, _sTableName,_rWinName ); +} +//------------------------------------------------------------------------------ +void OQueryTableView::AddTabWin(const ::rtl::OUString& _rTableName, const ::rtl::OUString& _rAliasName, 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 _rTableName voll qualifiziert, das OQueryDesignView erwartet aber einen String, der + // nur aus Schema und Tabelle besteht und keinen Katalog enthaelt. + Reference< XConnection> xConnection = m_pView->getController().getConnection(); + if(!xConnection.is()) + return; + try + { + Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + ::rtl::OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents(xMetaData, + _rTableName, + sCatalog, + sSchema, + sTable, + ::dbtools::eInDataManipulation); + ::rtl::OUString sRealName(sSchema); + if (sRealName.getLength()) + sRealName+= ::rtl::OUString('.'); + sRealName += sTable; + + AddTabWin(_rTableName, sRealName, _rAliasName, bNewTable); + } + catch(SQLException&) + { + OSL_ASSERT(!"qualifiedNameComponents"); + } +} +// ----------------------------------------------------------------------------- +// find the table which has a foreign key with this referencedTable name +Reference<XPropertySet> getKeyReferencedTo(const Reference<XIndexAccess>& _rxKeys,const ::rtl::OUString& _rReferencedTable) +{ + if(!_rxKeys.is()) + return Reference<XPropertySet>(); + + if ( !_rxKeys.is() ) + return Reference<XPropertySet>(); + // search the one and only primary key + const sal_Int32 nCount = _rxKeys->getCount(); + for(sal_Int32 i=0;i<nCount ;++i) + { + Reference<XPropertySet> xKey(_rxKeys->getByIndex(i),UNO_QUERY); + 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>(); +} +//------------------------------------------------------------------------------ +void OQueryTableView::AddTabWin(const ::rtl::OUString& _rComposedName, const ::rtl::OUString& _rTableName, const ::rtl::OUString& strAlias, sal_Bool bNewTable) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + DBG_ASSERT(_rTableName.getLength() || strAlias.getLength(), "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 + + // neue Datenstruktur erzeugen + // first check if this already hav it's data + sal_Bool bAppend = bNewTable; + TTableWindowData::value_type pNewTabWinData; + TTableWindowData* pWindowData = getDesignView()->getController().getTableWindowData(); + TTableWindowData::iterator aWinIter = pWindowData->begin(); + TTableWindowData::iterator aWinEnd = pWindowData->end(); + for(;aWinIter != aWinEnd;++aWinIter) + { + pNewTabWinData = *aWinIter; + if (pNewTabWinData && pNewTabWinData->GetWinName() == strAlias && pNewTabWinData->GetComposedName() == _rComposedName && pNewTabWinData->GetTableName() == _rTableName) + break; + } + if ( !bAppend ) + bAppend = ( aWinIter == aWinEnd ); + if ( bAppend ) + pNewTabWinData = createTableWindowData(_rComposedName, _rTableName, strAlias); + // die TabWinData brauche ich nicht in die entsprechende Liste der DocShell eintragen, das macht ShowTabWin + + // neues Fenster erzeugen + OQueryTableWindow* pNewTabWin = static_cast<OQueryTableWindow*>(createWindow(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,bAppend); + if(!bSuccess) + { + // reset table window + pUndoAction->SetTabWin(NULL); + pUndoAction->SetOwnership(sal_False); + + delete pUndoAction; + return; + } + + // Relationen zwischen den einzelnen Tabellen anzeigen + OTableWindowMap* pTabWins = GetTabWinMap(); + if(bNewTable && !pTabWins->empty() && _rTableName.getLength()) + { + modified(); + if ( m_pAccessible ) + m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD, + Any(), + makeAny(pNewTabWin->GetAccessible()) + ); + + do { + + if ( pNewTabWin->GetData()->isQuery() ) + break; + + try + { + ////////////////////////////////////////////////////////////////////// + // find relations between the table an the tables already inserted + Reference< XIndexAccess> xKeyIndex = pNewTabWin->GetData()->getKeys(); + if ( !xKeyIndex.is() ) + break; + + Reference<XNameAccess> xFKeyColumns; + ::rtl::OUString aReferencedTable; + Reference<XColumnsSupplier> xColumnsSupplier; + + const sal_Int32 nKeyCount = xKeyIndex->getCount(); + for ( sal_Int32 i=0; i<nKeyCount ; ++i ) + { + Reference< XPropertySet > xProp( xKeyIndex->getByIndex(i), UNO_QUERY_THROW ); + xColumnsSupplier.set( xProp, UNO_QUERY_THROW ); + xFKeyColumns.set( xColumnsSupplier->getColumns(), UNO_QUERY_THROW ); + + sal_Int32 nKeyType = 0; + xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType; + + switch ( nKeyType ) + { + case KeyType::FOREIGN: + { // 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); + OTableWindowMap::const_iterator aEnd = pTabWins->end(); + if(aIter == aEnd) + { + for(aIter = pTabWins->begin();aIter != aEnd;++aIter) + { + OQueryTableWindow* pTabWinTmp = static_cast<OQueryTableWindow*>(aIter->second); + OSL_ENSURE( pTabWinTmp,"TableWindow is null!" ); + if ( pTabWinTmp != pNewTabWin && pTabWinTmp->GetComposedName() == aReferencedTable ) + break; + } + } + if ( aIter != aEnd && pNewTabWin != aIter->second ) + addConnections( this, *pNewTabWin, *static_cast<OQueryTableWindow*>(aIter->second), xFKeyColumns ); + } + break; + + case KeyType::PRIMARY: + { + // 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(); + OTableWindowMap::const_iterator aEnd = pTabWins->end(); + for(;aIter != aEnd;++aIter) + { + OQueryTableWindow* pTabWinTmp = static_cast<OQueryTableWindow*>(aIter->second); + if ( pTabWinTmp == pNewTabWin ) + continue; + + if ( pTabWinTmp->GetData()->isQuery() ) + continue; + + OSL_ENSURE(pTabWinTmp,"TableWindow is null!"); + Reference< XPropertySet > xFKKey = getKeyReferencedTo( pTabWinTmp->GetData()->getKeys(), pNewTabWin->GetComposedName() ); + if ( !xFKKey.is() ) + continue; + + Reference<XColumnsSupplier> xFKColumnsSupplier( xFKKey, UNO_QUERY_THROW ); + Reference< XNameAccess > xTColumns( xFKColumnsSupplier->getColumns(), UNO_QUERY_THROW ); + addConnections( this, *pTabWinTmp, *pNewTabWin, xTColumns ); + } + } + break; + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + } while ( false ); + } + + // mein Parent brauche ich, da es vom Loeschen erfahren soll + m_pView->getController().addUndoActionAndInvalidate( pUndoAction ); + + if (bSuccess && m_lnkTabWinsChangeHandler.IsSet()) + { + TabWinsChangeNotification aHint(TabWinsChangeNotification::AT_ADDED_WIN, pNewTabWin->GetAliasName()); + m_lnkTabWinsChangeHandler.Call(&aHint); + } +} +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +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,true); + if ( !pConn ) + { + // neues Daten-Objekt + OQueryTableConnectionData* pNewConnectionData = new OQueryTableConnectionData(pSourceWin->GetData(), pDestWin->GetData()); + TTableConnectionData::value_type aNewConnectionData(pNewConnectionData); + + 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 + + pNewConnectionData->SetFieldIndex(JTCS_FROM, nSourceFieldIndex); + pNewConnectionData->SetFieldIndex(JTCS_TO, nDestFieldIndex); + + pNewConnectionData->SetFieldType(JTCS_FROM, eSourceFieldType); + pNewConnectionData->SetFieldType(JTCS_TO, eDestFieldType); + + pNewConnectionData->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 ); + + connectionModified(this,pConn,sal_False); + } +} +// ----------------------------------------------------------------------------- +void OQueryTableView::ConnDoubleClicked(OTableConnection* pConnection) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + if( openJoinDialog(this,pConnection->GetData(),FALSE) ) + { + connectionModified(this,pConnection,sal_False); + SelectConn( pConnection ); + } +} +// ----------------------------------------------------------------------------- +void OQueryTableView::createNewConnection() +{ + TTableConnectionData::value_type pData(new OQueryTableConnectionData()); + if( openJoinDialog(this,pData,TRUE) ) + { + OTableWindowMap* pMap = GetTabWinMap(); + OQueryTableWindow* pSourceWin = static_cast< OQueryTableWindow*>((*pMap)[pData->getReferencingTable()->GetWinName()]); + OQueryTableWindow* pDestWin = static_cast< OQueryTableWindow*>((*pMap)[pData->getReferencedTable()->GetWinName()]); + // first we have to look if the this connection already exists + OTableConnection* pConn = GetTabConn(pSourceWin,pDestWin,true); + sal_Bool bNew = sal_True; + if ( pConn ) + { + pConn->GetData()->CopyFrom( *pData ); + bNew = sal_False; + } + else + { + // create a new conenction and append it + OQueryTableConnection* pQConn = new OQueryTableConnection(this, pData); + GetConnection(pQConn); + pConn = pQConn; + } + connectionModified(this,pConn,bNew); + if ( !bNew && pConn == GetSelectedConn() ) // our connection was selected before so we have to reselect it + SelectConn( pConn ); + } +} +//------------------------------------------------------------------------------ +bool OQueryTableView::RemoveConnection( OTableConnection* _pConnection,sal_Bool /*_bDelete*/ ) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + + // we don't want that our connection will be deleted, we put it in the undo manager + bool bRet = OJoinTableView::RemoveConnection( _pConnection,sal_False); + + // add undo action + addUndoAction( this, + new OQueryDelTabConnUndoAction(this), + static_cast< OQueryTableConnection*>(_pConnection), + sal_True); + return bRet; +} + +//------------------------------------------------------------------------------ +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, OTableFieldDescRef& rInfo, sal_uInt16& rCnt) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + rCnt = 0; + OTableWindowMap::const_iterator aIter = GetTabWinMap()->begin(); + OTableWindowMap::const_iterator aEnd = GetTabWinMap()->end(); + for(;aIter != aEnd;++aIter) + { + if(static_cast<OQueryTableWindow*>(aIter->second)->ExistsField(rFieldName, rInfo)) + ++rCnt; + } + + return rCnt == 1; +} + +//------------------------------------------------------------------------------ +void OQueryTableView::RemoveTabWin(OTableWindow* pTabWin) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + DBG_ASSERT(pTabWin != NULL, "OQueryTableView::RemoveTabWin : Fenster sollte ungleich NULL sein !"); + + // mein Parent brauche ich, da es vom Loeschen erfahren soll + OQueryDesignView* pParent = static_cast<OQueryDesignView*>(getDesignView()); + + SfxUndoManager* pUndoMgr = m_pView->getController().getUndoMgr(); + pUndoMgr->EnterListAction( String( ModuleRes(STR_QUERY_UNDO_TABWINDELETE) ), String() ); + + // Undo-Action anlegen + OQueryTabWinDelUndoAct* pUndoAction = new OQueryTabWinDelUndoAct(this); + pUndoAction->SetTabWin(static_cast< OQueryTableWindow*>(pTabWin)); + + // und Fenster verstecken + HideTabWin(static_cast< OQueryTableWindow*>(pTabWin), pUndoAction); + + // Undo Actions und Loeschen der Felder in SelectionBrowseBox + pParent->TableDeleted( static_cast< OQueryTableWindowData*>(pTabWin->GetData().get())->GetAliasName() ); + + m_pView->getController().addUndoActionAndInvalidate( pUndoAction ); + pUndoMgr->LeaveListAction(); + + if (m_lnkTabWinsChangeHandler.IsSet()) + { + TabWinsChangeNotification aHint(TabWinsChangeNotification::AT_REMOVED_WIN, static_cast< OQueryTableWindow*>(pTabWin)->GetAliasName()); + m_lnkTabWinsChangeHandler.Call(&aHint); + } + + modified(); + if ( m_pAccessible ) + m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD, + makeAny(pTabWin->GetAccessible()), + Any() + ); +} + +//------------------------------------------------------------------------ +void OQueryTableView::EnsureVisible(const OTableWindow* pWin) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + + Invalidate(INVALIDATE_NOCHILDREN); + OJoinTableView::EnsureVisible(pWin); +} + +//------------------------------------------------------------------------ +void OQueryTableView::GetConnection(OQueryTableConnection* pConn) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + // bei mir und dem Dokument einfuegen + + addConnection( pConn ); +} + +//------------------------------------------------------------------------ +void OQueryTableView::DropConnection(OQueryTableConnection* pConn) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + // Selektion beachten + // bei mir und dem Dokument rausnehmen + RemoveConnection( pConn ,sal_False); +} + +//------------------------------------------------------------------------ +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(); + OTableWindowMap::iterator aEnd = pTabWins->end(); + for ( ;aIter != aEnd ; ++aIter ) + if ( aIter->second == pTabWin ) + { + pTabWins->erase( aIter ); + break; + } + + pTabWin->Hide(); // nicht zerstoeren, steht im Undo!! + + // die Daten zum TabWin muessen auch aus meiner Verantwortung entlassen werden + TTableWindowData* pTabWinDataList = m_pView->getController().getTableWindowData(); + pTabWinDataList->erase( ::std::remove(pTabWinDataList->begin(),pTabWinDataList->end(),pTabWin->GetData()),pTabWinDataList->end()); + // 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 + sal_Int16 nCnt = 0; + const ::std::vector<OTableConnection*>* pTabConList = getTableConnections(); + ::std::vector<OTableConnection*>::const_iterator aIter2 = pTabConList->begin(); + for(;aIter2 != pTabConList->end();)// the end may change + { + 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() ) + { + // add to undo list + pUndoAction->InsertConnection(pTmpEntry); + + // call base class because we append an undo action + // but this time we are in a undo action list + OJoinTableView::RemoveConnection(pTmpEntry,sal_False); + aIter2 = pTabConList->begin(); + ++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(SID_BROWSER_CLEAR_QUERY); + } +} + +//------------------------------------------------------------------------ +sal_Bool OQueryTableView::ShowTabWin( OQueryTableWindow* pTabWin, OQueryTabWinUndoAct* pUndoAction,sal_Bool _bAppend ) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + + sal_Bool bSuccess = sal_False; + + if (pTabWin) + { + if (pTabWin->Init()) + { + TTableWindowData::value_type 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 + ::rtl::OUString sName = static_cast< OQueryTableWindowData*>(pData.get())->GetAliasName(); + OSL_ENSURE(GetTabWinMap()->find(sName) == GetTabWinMap()->end(),"Alias name already in list!"); + GetTabWinMap()->insert(OTableWindowMap::value_type(sName,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 + ::std::vector<OTableConnection*>* pTableCon = pUndoAction->GetTabConnList(); + ::std::vector<OTableConnection*>::iterator aIter = pTableCon->begin(); + ::std::vector<OTableConnection*>::iterator aEnd = pTableCon->end(); + + for(;aIter != aEnd;++aIter) + addConnection(*aIter); // add all connections from the undo action + + pTableCon->clear(); + + // und die Daten des Fensters ebenfalls in Liste (des Docs) + if(_bAppend) + 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) + pTabWin->clearListBox(); + delete pTabWin; + } + } + + // damit habe ich das Doc natuerlich modifiziert + if(!m_pView->getController().isReadOnly()) + m_pView->getController().setModified( sal_True ); + + m_pView->getController().InvalidateFeature(SID_BROWSER_CLEAR_QUERY); + + return bSuccess; +} +//------------------------------------------------------------------------ +void OQueryTableView::InsertField(const OTableFieldDescRef& rInfo) +{ + DBG_CHKTHIS(OQueryTableView,NULL); + DBG_ASSERT(getDesignView() != NULL, "OQueryTableView::InsertField : habe kein Parent !"); + static_cast<OQueryDesignView*>(getDesignView())->InsertField(rInfo); +} +//------------------------------------------------------------------------------ +sal_Bool OQueryTableView::ExistsAVisitedConn(const OQueryTableWindow* pFrom) const +{ + DBG_CHKTHIS(OQueryTableView,NULL); + const ::std::vector<OTableConnection*>* pList = getTableConnections(); + if (pList) + { + ::std::vector<OTableConnection*>::const_iterator aIter = pList->begin(); + ::std::vector<OTableConnection*>::const_iterator aEnd = pList->end(); + for(;aIter != aEnd;++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; +} +// ----------------------------------------------------------------------------- +void OQueryTableView::onNoColumns_throw() +{ + String sError( ModuleRes( STR_STATEMENT_WITHOUT_RESULT_SET ) ); + ::dbtools::throwSQLException( sError, ::dbtools::SQL_GENERAL_ERROR, NULL ); +} +//------------------------------------------------------------------------------ +bool OQueryTableView::supressCrossNaturalJoin(const TTableConnectionData::value_type& _pData) const +{ + OQueryTableConnectionData* pQueryData = static_cast<OQueryTableConnectionData*>(_pData.get()); + return pQueryData && (pQueryData->GetJoinType() == CROSS_JOIN); +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryTextView.cxx b/dbaccess/source/ui/querydesign/QueryTextView.cxx new file mode 100644 index 000000000000..3e19ab75aa62 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryTextView.cxx @@ -0,0 +1,153 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "QueryTextView.hxx" +#include "querycontainerwindow.hxx" +#include "QueryViewSwitch.hxx" +#include "sqledit.hxx" +#include "undosqledit.hxx" +#include "browserids.hxx" +#include "querycontroller.hxx" +#include "dbu_qry.hrc" +#include "dbustrings.hrc" +#include <toolkit/unohlp.hxx> +#include <vcl/split.hxx> +#include <vcl/svapp.hxx> +#include <comphelper/types.hxx> +#include "QueryDesignView.hxx" + +using namespace dbaui; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +// ----------------------------------------------------------------------------- + +// end of temp classes +// ------------------------------------------------------------------------- +DBG_NAME(OQueryTextView) +OQueryTextView::OQueryTextView(OQueryContainerWindow* _pParent) + :Window(_pParent) +{ + DBG_CTOR(OQueryTextView,NULL); + m_pEdit = new OSqlEdit(this); + m_pEdit->SetRightToLeft(FALSE); + m_pEdit->ClearModifyFlag(); + m_pEdit->SaveValue(); + m_pEdit->SetPosPixel( Point( 0, 0 ) ); + m_pEdit->Show(); +} +// ----------------------------------------------------------------------------- +OQueryTextView::~OQueryTextView() +{ + DBG_DTOR(OQueryTextView,NULL); + ::std::auto_ptr<Window> aTemp(m_pEdit); + m_pEdit = NULL; +} +// ----------------------------------------------------------------------------- +void OQueryTextView::GetFocus() +{ + if ( m_pEdit ) + m_pEdit->GrabFocus(); +} +// ------------------------------------------------------------------------- +void OQueryTextView::Resize() +{ + Window::Resize(); + m_pEdit->SetSizePixel( GetOutputSizePixel() ); +} +// ----------------------------------------------------------------------------- +// check if the statement is correct when not returning false +sal_Bool OQueryTextView::checkStatement() +{ + return sal_True; +} +// ----------------------------------------------------------------------------- +::rtl::OUString OQueryTextView::getStatement() +{ + return m_pEdit->GetText(); +} +// ----------------------------------------------------------------------------- +void OQueryTextView::setReadOnly(sal_Bool _bReadOnly) +{ + m_pEdit->SetReadOnly(_bReadOnly); +} +// ----------------------------------------------------------------------------- +void OQueryTextView::clear() +{ + OSqlEditUndoAct* pUndoAct = new OSqlEditUndoAct( m_pEdit ); + + pUndoAct->SetOriginalText( m_pEdit->GetText() ); + getContainerWindow()->getDesignView()->getController().addUndoActionAndInvalidate( pUndoAct ); + + m_pEdit->SetText(String()); +} +// ----------------------------------------------------------------------------- +void OQueryTextView::setStatement(const ::rtl::OUString& _rsStatement) +{ + m_pEdit->SetText(_rsStatement); +} +// ----------------------------------------------------------------------------- +void OQueryTextView::copy() +{ + if(!m_pEdit->IsInAccelAct() ) + m_pEdit->Copy(); +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryTextView::isCutAllowed() +{ + return m_pEdit->GetSelected().Len() != 0; +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryTextView::isPasteAllowed() +{ + return sal_True; +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryTextView::isCopyAllowed() +{ + return sal_True; +} +// ----------------------------------------------------------------------------- +void OQueryTextView::cut() +{ + if(!m_pEdit->IsInAccelAct() ) + m_pEdit->Cut(); + getContainerWindow()->getDesignView()->getController().setModified(sal_True); +} +// ----------------------------------------------------------------------------- +void OQueryTextView::paste() +{ + if(!m_pEdit->IsInAccelAct() ) + m_pEdit->Paste(); + getContainerWindow()->getDesignView()->getController().setModified(sal_True); +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/QueryViewSwitch.cxx b/dbaccess/source/ui/querydesign/QueryViewSwitch.cxx new file mode 100644 index 000000000000..792d283ee8a3 --- /dev/null +++ b/dbaccess/source/ui/querydesign/QueryViewSwitch.cxx @@ -0,0 +1,344 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "QueryViewSwitch.hxx" +#include "QueryDesignView.hxx" +#include "QueryTextView.hxx" +#include "querycontainerwindow.hxx" +#include "dbu_qry.hrc" +#include "browserids.hxx" +#include "adtabdlg.hxx" +#include "querycontroller.hxx" +#include "sqledit.hxx" +#include "querycontainerwindow.hxx" + +using namespace dbaui; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + +DBG_NAME(OQueryViewSwitch) +OQueryViewSwitch::OQueryViewSwitch(OQueryContainerWindow* _pParent, OQueryController& _rController,const Reference< XMultiServiceFactory >& _rFactory) +: m_bAddTableDialogWasVisible(sal_False) +{ + DBG_CTOR(OQueryViewSwitch,NULL); + + m_pTextView = new OQueryTextView(_pParent); + m_pDesignView = new OQueryDesignView( _pParent, _rController, _rFactory ); +} +// ----------------------------------------------------------------------------- +OQueryViewSwitch::~OQueryViewSwitch() +{ + DBG_DTOR(OQueryViewSwitch,NULL); + { + ::std::auto_ptr<Window> aTemp(m_pTextView); + m_pTextView = NULL; + } + { + ::std::auto_ptr<Window> aTemp(m_pDesignView); + m_pDesignView = NULL; + } +} +// ------------------------------------------------------------------------- +void OQueryViewSwitch::Construct() +{ + m_pDesignView->Construct( ); +} +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::initialize() +{ + // initially be in SQL mode + m_pTextView->Show(); + m_pDesignView->initialize(); +} +// ------------------------------------------------------------------------- +void OQueryViewSwitch::resizeDocumentView(Rectangle& _rPlayground) +{ + m_pTextView->SetPosSizePixel( _rPlayground.TopLeft(), _rPlayground.GetSize() ); + m_pDesignView->SetPosSizePixel( _rPlayground.TopLeft(), _rPlayground.GetSize() ); + + // just for completeness: there is no space left, we occupied it all ... + _rPlayground.SetPos( _rPlayground.BottomRight() ); + _rPlayground.SetSize( Size( 0, 0 ) ); +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryViewSwitch::checkStatement() +{ + if(m_pTextView->IsVisible()) + return m_pTextView->checkStatement(); + return m_pDesignView->checkStatement(); +} +// ----------------------------------------------------------------------------- +::rtl::OUString OQueryViewSwitch::getStatement() +{ + if(m_pTextView->IsVisible()) + return m_pTextView->getStatement(); + return m_pDesignView->getStatement(); +} +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::setReadOnly(sal_Bool _bReadOnly) +{ + if(m_pTextView->IsVisible()) + m_pTextView->setReadOnly(_bReadOnly); + else + m_pDesignView->setReadOnly(_bReadOnly); +} +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::clear() +{ + if(m_pTextView->IsVisible()) + m_pTextView->clear(); + else + m_pDesignView->clear(); +} +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::GrabFocus() +{ + if ( m_pTextView && m_pTextView->IsVisible() ) + m_pTextView->GrabFocus(); + else if ( m_pDesignView && m_pDesignView->IsVisible() ) + m_pDesignView->GrabFocus(); +} +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::setStatement(const ::rtl::OUString& _rsStatement) +{ + if(m_pTextView->IsVisible()) + m_pTextView->setStatement(_rsStatement); + else + m_pDesignView->setStatement(_rsStatement); +} +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::copy() +{ + if(m_pTextView->IsVisible()) + m_pTextView->copy(); + else + m_pDesignView->copy(); +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryViewSwitch::isCutAllowed() +{ + if(m_pTextView->IsVisible()) + return m_pTextView->isCutAllowed(); + return m_pDesignView->isCutAllowed(); +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryViewSwitch::isCopyAllowed() +{ + if(m_pTextView->IsVisible()) + return m_pTextView->isCopyAllowed(); + return m_pDesignView->isCopyAllowed(); +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryViewSwitch::isPasteAllowed() +{ + if(m_pTextView->IsVisible()) + return m_pTextView->isPasteAllowed(); + return m_pDesignView->isPasteAllowed(); +} +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::cut() +{ + if(m_pTextView->IsVisible()) + m_pTextView->cut(); + else + m_pDesignView->cut(); +} +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::paste() +{ + if(m_pTextView->IsVisible()) + m_pTextView->paste(); + else + m_pDesignView->paste(); +} +// ----------------------------------------------------------------------------- +OQueryContainerWindow* OQueryViewSwitch::getContainer() const +{ + Window* pDesignParent = getDesignView() ? getDesignView()->GetParent() : NULL; + return static_cast< OQueryContainerWindow* >( pDesignParent ); +} + +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::impl_forceSQLView() +{ + OAddTableDlg* pAddTabDialog( getAddTableDialog() ); + + // hide the "Add Table" dialog + m_bAddTableDialogWasVisible = pAddTabDialog ? pAddTabDialog->IsVisible() : false; + if ( m_bAddTableDialogWasVisible ) + pAddTabDialog->Hide(); + + // tell the views they're in/active + m_pDesignView->stopTimer(); + m_pTextView->getSqlEdit()->startTimer(); + + // set the most recent statement at the text view + m_pTextView->clear(); + m_pTextView->setStatement(static_cast<OQueryController&>(m_pDesignView->getController()).getStatement()); +} + +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::forceInitialView() +{ + OQueryController& rQueryController( static_cast< OQueryController& >( m_pDesignView->getController() ) ); + const sal_Bool bGraphicalDesign = rQueryController.isGraphicalDesign(); + if ( !bGraphicalDesign ) + impl_forceSQLView(); + else + { + // tell the text view it's inactive now + m_pTextView->getSqlEdit()->stopTimer(); + + // update the "Add Table" dialog + OAddTableDlg* pAddTabDialog( getAddTableDialog() ); + if ( pAddTabDialog ) + pAddTabDialog->Update(); + + // initialize the design view + m_pDesignView->initByFieldDescriptions( rQueryController.getFieldInformation() ); + + // tell the design view it's active now + m_pDesignView->startTimer(); + } + + impl_postViewSwitch( bGraphicalDesign, true ); +} + +// ----------------------------------------------------------------------------- +bool OQueryViewSwitch::switchView( ::dbtools::SQLExceptionInfo* _pErrorInfo ) +{ + sal_Bool bRet = sal_True; + sal_Bool bGraphicalDesign = static_cast<OQueryController&>(m_pDesignView->getController()).isGraphicalDesign(); + + if ( !bGraphicalDesign ) + { + impl_forceSQLView(); + } + else + { + // tell the text view it's inactive now + m_pTextView->getSqlEdit()->stopTimer(); + + // update the "Add Table" dialog + OAddTableDlg* pAddTabDialog( getAddTableDialog() ); + if ( pAddTabDialog ) + pAddTabDialog->Update(); + + // initialize the design view + bRet = m_pDesignView->initByParseIterator( _pErrorInfo ); + + // tell the design view it's active now + m_pDesignView->startTimer(); + } + + return impl_postViewSwitch( bGraphicalDesign, bRet ); +} + +// ----------------------------------------------------------------------------- +bool OQueryViewSwitch::impl_postViewSwitch( const bool i_bGraphicalDesign, const bool i_bSuccess ) +{ + if ( i_bSuccess ) + { + m_pTextView->Show ( !i_bGraphicalDesign ); + m_pDesignView->Show ( i_bGraphicalDesign ); + OAddTableDlg* pAddTabDialog( getAddTableDialog() ); + if ( pAddTabDialog ) + if ( i_bGraphicalDesign && m_bAddTableDialogWasVisible ) + pAddTabDialog->Show(); + + GrabFocus(); + } + + OQueryContainerWindow* pContainer = getContainer(); + if ( pContainer ) + pContainer->Resize(); + + m_pDesignView->getController().getUndoMgr()->Clear(); + m_pDesignView->getController().InvalidateAll(); + + return i_bSuccess; +} + +// ----------------------------------------------------------------------------- +OAddTableDlg* OQueryViewSwitch::getAddTableDialog() +{ + if ( !m_pDesignView ) + return NULL; + return m_pDesignView->getController().getAddTableDialog(); +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryViewSwitch::isSlotEnabled(sal_Int32 _nSlotId) +{ + return m_pDesignView->isSlotEnabled(_nSlotId); +} +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::setSlotEnabled(sal_Int32 _nSlotId,sal_Bool _bEnable) +{ + m_pDesignView->setSlotEnabled(_nSlotId,_bEnable); +} +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::SaveUIConfig() +{ + if(m_pDesignView->IsVisible()) + m_pDesignView->SaveUIConfig(); +} +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::SetPosSizePixel( Point _rPt,Size _rSize) +{ + m_pDesignView->SetPosSizePixel( _rPt,_rSize); + m_pDesignView->Resize(); + m_pTextView->SetPosSizePixel( _rPt,_rSize); +} +// ----------------------------------------------------------------------------- +Reference< XMultiServiceFactory > OQueryViewSwitch::getORB() const +{ + return m_pDesignView->getORB(); +} +// ----------------------------------------------------------------------------- +bool OQueryViewSwitch::reset( ::dbtools::SQLExceptionInfo* _pErrorInfo ) +{ + m_pDesignView->reset(); + if ( !m_pDesignView->initByParseIterator( _pErrorInfo ) ) + return false; + + if ( switchView( _pErrorInfo ) ) + return false; + + return true; +} +// ----------------------------------------------------------------------------- +void OQueryViewSwitch::setNoneVisbleRow(sal_Int32 _nRows) +{ + if(m_pDesignView) + m_pDesignView->setNoneVisbleRow(_nRows); +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx b/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx new file mode 100644 index 000000000000..a3763deafc02 --- /dev/null +++ b/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx @@ -0,0 +1,2834 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "SelectionBrowseBox.hxx" +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include "QueryDesignView.hxx" +#include "querycontroller.hxx" +#include "QueryTableView.hxx" +#include "browserids.hxx" +#include <comphelper/types.hxx> +#include "TableFieldInfo.hxx" +#include "dbu_qry.hrc" +#include "dbaccess_helpid.hrc" +#include <tools/debug.hxx> +#include <com/sun/star/container/XNameAccess.hpp> +#include "dbustrings.hrc" +#include "QTableWindow.hxx" +#include "QueryTableView.hxx" +#include <vcl/msgbox.hxx> +#include "QueryDesignFieldUndoAct.hxx" +#include <svx/dbexch.hrc> +#include <comphelper/stl_types.hxx> +#include <comphelper/extract.hxx> +#include "sqlmessage.hxx" +#include "UITools.hxx" + +using namespace ::svt; +using namespace ::dbaui; +using namespace ::connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::accessibility; + +const String g_strOne = String::CreateFromAscii("1"); +const String g_strZero = String::CreateFromAscii("0"); + +#define DEFAULT_QUERY_COLS 20 +#define DEFAULT_SIZE GetTextWidth(g_strZero) * 30 +#define CHECKBOX_SIZE 10 +#define HANDLE_ID 0 +#define HANDLE_COLUMN_WITDH 70 + +#define SQL_ISRULEOR2(pParseNode, e1,e2) ((pParseNode)->isRule() && (\ + (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e1) || \ + (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e2))) + + +// ----------------------------------------------------------------------------- +namespace +{ + sal_Bool isFieldNameAsterix(const ::rtl::OUString& _sFieldName ) + { + sal_Bool bAsterix = !(_sFieldName.getLength() && _sFieldName.toChar() != '*'); + if ( !bAsterix ) + { + String sName = _sFieldName; + xub_StrLen nTokenCount = sName.GetTokenCount('.'); + if ( (nTokenCount == 2 && sName.GetToken(1,'.').GetChar(0) == '*' ) + || (nTokenCount == 3 && sName.GetToken(2,'.').GetChar(0) == '*' ) ) + { + bAsterix = sal_True; + } + } + return bAsterix; + } + // ----------------------------------------------------------------------------- + sal_Bool lcl_SupportsCoreSQLGrammar(const Reference< XConnection>& _xConnection) + { + sal_Bool bSupportsCoreGrammar = sal_False; + if ( _xConnection.is() ) + { + try + { + Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData(); + bSupportsCoreGrammar = xMetaData.is() && xMetaData->supportsCoreSQLGrammar(); + } + catch(Exception&) + { + } + } + return bSupportsCoreGrammar; + } +} + +DBG_NAME(OSelectionBrowseBox) +//------------------------------------------------------------------------------ +OSelectionBrowseBox::OSelectionBrowseBox( Window* pParent ) + :EditBrowseBox( pParent,EBBF_NOROWPICTURE, WB_3DLOOK, BROWSER_COLUMNSELECTION | BROWSER_KEEPSELECTION | BROWSER_HIDESELECT | + BROWSER_HIDECURSOR | BROWSER_HLINESFULL | BROWSER_VLINESFULL ) + ,m_aFunctionStrings(ModuleRes(STR_QUERY_FUNCTIONS)) + ,m_nVisibleCount(0) + ,m_bOrderByUnRelated(sal_True) + ,m_bGroupByUnRelated(sal_True) + ,m_bStopTimer(sal_False) + ,m_bWasEditing(sal_False) + ,m_bDisableErrorBox(sal_False) + ,m_bInUndoMode(sal_False) +{ + DBG_CTOR(OSelectionBrowseBox,NULL); + SetHelpId(HID_CTL_QRYDGNCRIT); + + m_nMode = BROWSER_COLUMNSELECTION | BROWSER_HIDESELECT + | BROWSER_KEEPSELECTION | BROWSER_HIDECURSOR + | BROWSER_HLINESFULL | BROWSER_VLINESFULL + | BROWSER_HEADERBAR_NEW ; + + m_pTextCell = new Edit(&GetDataWindow(), 0); + m_pVisibleCell = new CheckBoxControl(&GetDataWindow()); + m_pTableCell = new ListBoxControl(&GetDataWindow()); m_pTableCell->SetDropDownLineCount( 20 ); + m_pFieldCell = new ComboBoxControl(&GetDataWindow()); m_pFieldCell->SetDropDownLineCount( 20 ); + m_pOrderCell = new ListBoxControl(&GetDataWindow()); + m_pFunctionCell = new ListBoxControl(&GetDataWindow()); m_pFunctionCell->SetDropDownLineCount( 20 ); + + m_pVisibleCell->SetHelpId(HID_QRYDGN_ROW_VISIBLE); + m_pTableCell->SetHelpId(HID_QRYDGN_ROW_TABLE); + m_pFieldCell->SetHelpId(HID_QRYDGN_ROW_FIELD); + m_pOrderCell->SetHelpId(HID_QRYDGN_ROW_ORDER); + m_pFunctionCell->SetHelpId(HID_QRYDGN_ROW_FUNCTION); + + ////////////////////////////////////////////////////////////////////// + // TriState der ::com::sun::star::form::CheckBox abschalten + m_pVisibleCell->GetBox().EnableTriState( sal_False ); + + Font aTitleFont = OutputDevice::GetDefaultFont( DEFAULTFONT_SANS_UNICODE,Window::GetSettings().GetLanguage(),DEFAULTFONT_FLAGS_ONLYONE); + aTitleFont.SetSize(Size(0, 6)); + SetTitleFont(aTitleFont); + + String aTxt(ModuleRes(STR_QUERY_SORTTEXT)); + xub_StrLen nCount = aTxt.GetTokenCount(); + xub_StrLen nIdx = 0; + for (; nIdx < nCount; nIdx++) + m_pOrderCell->InsertEntry(aTxt.GetToken(nIdx)); + + for(long i=0;i < BROW_ROW_CNT;i++) + m_bVisibleRow.push_back(sal_True); + + m_bVisibleRow[BROW_FUNCTION_ROW] = sal_False; // zuerst ausblenden + + m_timerInvalidate.SetTimeout(200); + m_timerInvalidate.SetTimeoutHdl(LINK(this, OSelectionBrowseBox, OnInvalidateTimer)); + m_timerInvalidate.Start(); +} + +//------------------------------------------------------------------------------ +OSelectionBrowseBox::~OSelectionBrowseBox() +{ + DBG_DTOR(OSelectionBrowseBox,NULL); + + delete m_pTextCell; + delete m_pVisibleCell; + delete m_pFieldCell; + delete m_pTableCell; + delete m_pOrderCell; + delete m_pFunctionCell; +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::initialize() +{ + Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); + if(xConnection.is()) + { + const IParseContext& rContext = static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext(); + IParseContext::InternationalKeyCode eFunctions[] = { IParseContext::KEY_AVG,IParseContext::KEY_COUNT,IParseContext::KEY_MAX + ,IParseContext::KEY_MIN,IParseContext::KEY_SUM + ,IParseContext::KEY_EVERY + ,IParseContext::KEY_ANY + ,IParseContext::KEY_SOME + ,IParseContext::KEY_STDDEV_POP + ,IParseContext::KEY_STDDEV_SAMP + ,IParseContext::KEY_VAR_SAMP + ,IParseContext::KEY_VAR_POP + ,IParseContext::KEY_COLLECT + ,IParseContext::KEY_FUSION + ,IParseContext::KEY_INTERSECTION + }; + + String sGroup = m_aFunctionStrings.GetToken(m_aFunctionStrings.GetTokenCount() - 1); + m_aFunctionStrings = m_aFunctionStrings.GetToken(0); + + for (size_t i = 0; i < SAL_N_ELEMENTS(eFunctions); ++i) + { + m_aFunctionStrings += String(RTL_CONSTASCII_USTRINGPARAM(";")); + m_aFunctionStrings += String(ByteString(rContext.getIntlKeywordAscii(eFunctions[i])),RTL_TEXTENCODING_UTF8); + + } + m_aFunctionStrings += String(RTL_CONSTASCII_USTRINGPARAM(";")); + m_aFunctionStrings += sGroup; + + // Diese Funktionen stehen nur unter CORE zur Verfügung + if ( lcl_SupportsCoreSQLGrammar(xConnection) ) + { + xub_StrLen nCount = m_aFunctionStrings.GetTokenCount(); + for (xub_StrLen nIdx = 0; nIdx < nCount; nIdx++) + m_pFunctionCell->InsertEntry(m_aFunctionStrings.GetToken(nIdx)); + } + else // sonst nur COUNT(*) + { + m_pFunctionCell->InsertEntry(m_aFunctionStrings.GetToken(0)); + m_pFunctionCell->InsertEntry(m_aFunctionStrings.GetToken(2)); // 2 -> COUNT + } + try + { + Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + if ( xMetaData.is() ) + { + m_bOrderByUnRelated = xMetaData->supportsOrderByUnrelated(); + m_bGroupByUnRelated = xMetaData->supportsGroupByUnrelated(); + } + } + catch(Exception&) + { + } + } + + Init(); +} +//============================================================================== +OQueryDesignView* OSelectionBrowseBox::getDesignView() +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + OSL_ENSURE(static_cast<const OQueryDesignView*>(GetParent()),"Parent isn't an OQueryDesignView!"); + return static_cast<OQueryDesignView*>(GetParent()); +} +// ----------------------------------------------------------------------------- +OQueryDesignView* OSelectionBrowseBox::getDesignView() const +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + OSL_ENSURE(static_cast<const OQueryDesignView*>(GetParent()),"Parent isn't an OQueryDesignView!"); + return static_cast<OQueryDesignView*>(GetParent()); +} +namespace +{ + class OSelectionBrwBoxHeader : public ::svt::EditBrowserHeader + { + OSelectionBrowseBox* m_pBrowseBox; + protected: + virtual void Select(); + public: + OSelectionBrwBoxHeader(OSelectionBrowseBox* pParent); + }; + OSelectionBrwBoxHeader::OSelectionBrwBoxHeader(OSelectionBrowseBox* pParent) + : ::svt::EditBrowserHeader(pParent,WB_BUTTONSTYLE|WB_DRAG) + ,m_pBrowseBox(pParent) + { + } + + void OSelectionBrwBoxHeader::Select() + { + EditBrowserHeader::Select(); + m_pBrowseBox->GrabFocus(); + + BrowserMode nMode = m_pBrowseBox->GetMode(); + if ( 0 == m_pBrowseBox->GetSelectColumnCount() ) + { + m_pBrowseBox->DeactivateCell(); + // wenn es schon eine selektierte Spalte gibt, bin ich schon im richtigen Modus + if ( BROWSER_HIDESELECT == ( nMode & BROWSER_HIDESELECT ) ) + { + nMode &= ~BROWSER_HIDESELECT; + nMode |= BROWSER_MULTISELECTION; + m_pBrowseBox->SetMode( nMode ); + } + } + m_pBrowseBox->SelectColumnId( GetCurItemId() ); + m_pBrowseBox->DeactivateCell(); + } +} + +// ----------------------------------------------------------------------------- +BrowserHeader* OSelectionBrowseBox::imp_CreateHeaderBar(BrowseBox* /*pParent*/) +{ + return new OSelectionBrwBoxHeader(this); +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::ColumnMoved( USHORT nColId,BOOL _bCreateUndo ) +{ + EditBrowseBox::ColumnMoved( nColId ); + // swap the two columns + USHORT nNewPos = GetColumnPos( nColId ); + OTableFields& rFields = getFields(); + if ( rFields.size() > USHORT(nNewPos-1) ) + { + USHORT nOldPos = 0; + OTableFields::iterator aEnd = rFields.end(); + OTableFields::iterator aIter = rFields.begin(); + for (; aIter != aEnd && ( (*aIter)->GetColumnId() != nColId ); ++aIter,++nOldPos) + ; + + OSL_ENSURE( (nNewPos-1) != nOldPos && nOldPos < rFields.size(),"Old and new position are equal!"); + if ( aIter != aEnd ) + { + OTableFieldDescRef pOldEntry = rFields[nOldPos]; + rFields.erase(rFields.begin() + nOldPos); + rFields.insert(rFields.begin() + nNewPos - 1,pOldEntry); + + // create the undo action + if ( !m_bInUndoMode && _bCreateUndo ) + { + OTabFieldMovedUndoAct* pUndoAct = new OTabFieldMovedUndoAct(this); + pUndoAct->SetColumnPosition( nOldPos + 1); + pUndoAct->SetTabFieldDescr(pOldEntry); + + getDesignView()->getController().addUndoActionAndInvalidate(pUndoAct); + } + } + } + else + OSL_ENSURE(0,"Invalid column id!"); +} +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::Init() +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + + EditBrowseBox::Init(); + + // set the header bar + BrowserHeader* pNewHeaderBar = CreateHeaderBar(this); + pNewHeaderBar->SetMouseTransparent(sal_False); + + SetHeaderBar(pNewHeaderBar); + SetMode(m_nMode); + + Font aFont( GetDataWindow().GetFont() ); + aFont.SetWeight( WEIGHT_NORMAL ); + GetDataWindow().SetFont( aFont ); + + Size aHeight; + const Control* pControls[] = { m_pTextCell,m_pVisibleCell,m_pTableCell,m_pFieldCell }; + for(sal_Size i= 0; i < SAL_N_ELEMENTS(pControls);++i) + { + const Size aTemp( pControls[i]->GetOptimalSize(WINDOWSIZE_PREFERRED) ); + if ( aTemp.Height() > aHeight.Height() ) + aHeight.Height() = aTemp.Height(); + } + SetDataRowHeight(aHeight.Height()); + SetTitleLines(1); + // Anzahl der sichtbaren Zeilen ermitteln + for(long i=0;i<BROW_ROW_CNT;i++) + { + if(m_bVisibleRow[i]) + m_nVisibleCount++; + } + RowInserted(0, m_nVisibleCount, sal_False); + try + { + Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); + if(xConnection.is()) + { + Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + m_nMaxColumns = xMetaData.is() ? xMetaData->getMaxColumnsInSelect() : 0; + + } + else + m_nMaxColumns = 0; + } + catch(const SQLException&) + { + OSL_ENSURE(0,"Catched Exception when asking for database metadata options!"); + m_nMaxColumns = 0; + } +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::PreFill() +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + SetUpdateMode(sal_False); + + if (GetCurRow() != 0) + GoToRow(0); + + + static_cast< OQueryController& >( getDesignView()->getController() ).clearFields(); + + DeactivateCell(); + + RemoveColumns(); + InsertHandleColumn( HANDLE_COLUMN_WITDH ); + SetUpdateMode(sal_True); +} +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::ClearAll() +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + SetUpdateMode(sal_False); + + OTableFields::reverse_iterator aIter = getFields().rbegin(); + for ( ;aIter != getFields().rend(); ++aIter ) + { + if ( !(*aIter)->IsEmpty() ) + { + RemoveField( (*aIter)->GetColumnId() ); + aIter = getFields().rbegin(); + } + } + SetUpdateMode(sal_True); +} +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::SetReadOnly(sal_Bool bRO) +{ + if (bRO) + { + DeactivateCell(); + m_nMode &= ~BROWSER_HIDECURSOR; + SetMode(m_nMode); + } + else + { + m_nMode |= BROWSER_HIDECURSOR; + SetMode(m_nMode); + ActivateCell(); + } +} + +//------------------------------------------------------------------------------ +CellController* OSelectionBrowseBox::GetController(long nRow, sal_uInt16 nColId) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + if ( nColId > getFields().size() ) + return NULL; + OTableFieldDescRef pEntry = getFields()[nColId-1]; + DBG_ASSERT(pEntry.is(), "OSelectionBrowseBox::GetController : keine FieldDescription !"); + + if (!pEntry.is()) + return NULL; + + if (static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly()) + return NULL; + + long nCellIndex = GetRealRow(nRow); + switch (nCellIndex) + { + case BROW_FIELD_ROW: + return new ComboBoxCellController(m_pFieldCell); + case BROW_TABLE_ROW: + return new ListBoxCellController(m_pTableCell); + case BROW_VIS_ROW: + return new CheckBoxCellController(m_pVisibleCell); + case BROW_ORDER_ROW: + return new ListBoxCellController(m_pOrderCell); + case BROW_FUNCTION_ROW: + return new ListBoxCellController(m_pFunctionCell); + default: + return new EditCellController(m_pTextCell); + } +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::InitController(CellControllerRef& /*rController*/, long nRow, sal_uInt16 nColId) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + OSL_ENSURE(nColId != BROWSER_INVALIDID,"An Invalid Id was set!"); + if ( nColId == BROWSER_INVALIDID ) + return; + USHORT nPos = GetColumnPos(nColId); + if ( nPos == 0 || nPos == BROWSER_INVALIDID || nPos > getFields().size() ) + return; + OTableFieldDescRef pEntry = getFields()[nPos-1]; + DBG_ASSERT(pEntry.is(), "OSelectionBrowseBox::InitController : keine FieldDescription !"); + long nCellIndex = GetRealRow(nRow); + + switch (nCellIndex) + { + case BROW_FIELD_ROW: + { + m_pFieldCell->Clear(); + m_pFieldCell->SetText(String()); + + String aField(pEntry->GetField()); + String aTable(pEntry->GetAlias()); + + getDesignView()->fillValidFields(aTable, m_pFieldCell); + + // * durch alias.* ersetzen + if ((aField.GetChar(0) == '*') && aTable.Len()) + { + aField = aTable; + aField.AppendAscii(".*"); + } + m_pFieldCell->SetText(aField); + } break; + case BROW_TABLE_ROW: + { + m_pTableCell->Clear(); + enableControl(pEntry,m_pTableCell); + if ( !pEntry->isCondition() ) + { + OJoinTableView::OTableWindowMap* pTabWinList = getDesignView()->getTableView()->GetTabWinMap(); + if (pTabWinList) + { + OJoinTableView::OTableWindowMap::iterator aIter = pTabWinList->begin(); + OJoinTableView::OTableWindowMap::iterator aEnd = pTabWinList->end(); + + for(;aIter != aEnd;++aIter) + m_pTableCell->InsertEntry(static_cast<OQueryTableWindow*>(aIter->second)->GetAliasName()); + + m_pTableCell->InsertEntry(String(ModuleRes(STR_QUERY_NOTABLE)), 0); + if (pEntry->GetAlias().getLength()) + m_pTableCell->SelectEntry(pEntry->GetAlias()); + else + m_pTableCell->SelectEntry(String(ModuleRes(STR_QUERY_NOTABLE))); + } + } + } break; + case BROW_VIS_ROW: + { + m_pVisibleCell->GetBox().Check(pEntry->IsVisible()); + m_pVisibleCell->GetBox().SaveValue(); + + enableControl(pEntry,m_pTextCell); + + if(!pEntry->IsVisible() && pEntry->GetOrderDir() != ORDER_NONE && !m_bOrderByUnRelated) + { + // Spalte muss sichtbar sein, um im ORDER BY aufzutauchen + pEntry->SetVisible(sal_True); + m_pVisibleCell->GetBox().Check(pEntry->IsVisible()); + m_pVisibleCell->GetBox().SaveValue(); + m_pVisibleCell->GetBox().Disable(); + m_pVisibleCell->GetBox().EnableInput(sal_False); + String aMessage(ModuleRes(STR_QRY_ORDERBY_UNRELATED)); + OQueryDesignView* paDView = getDesignView(); + InfoBox(paDView, aMessage).Execute(); + } + } break; + case BROW_ORDER_ROW: + m_pOrderCell->SelectEntryPos( + sal::static_int_cast< USHORT >(pEntry->GetOrderDir())); + enableControl(pEntry,m_pOrderCell); + break; + case BROW_COLUMNALIAS_ROW: + setTextCellContext(pEntry,pEntry->GetFieldAlias(),HID_QRYDGN_ROW_ALIAS); + break; + case BROW_FUNCTION_ROW: + setFunctionCell(pEntry); + break; + default: + { + sal_uInt16 nIdx = sal_uInt16(nCellIndex - BROW_CRIT1_ROW); + setTextCellContext(pEntry,pEntry->GetCriteria( nIdx ),HID_QRYDGN_ROW_CRIT); + } + } + Controller()->ClearModified(); +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::notifyTableFieldChanged(const String& _sOldAlias,const String& _sAlias,sal_Bool& _bListAction,USHORT _nColumnId) +{ + appendUndoAction(_sOldAlias,_sAlias,BROW_TABLE_ROW,_bListAction); + if ( m_bVisibleRow[BROW_TABLE_ROW] ) + RowModified(GetBrowseRow(BROW_TABLE_ROW), _nColumnId); +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::notifyFunctionFieldChanged(const String& _sOldFunctionName,const String& _sFunctionName,sal_Bool& _bListAction,USHORT _nColumnId) +{ + appendUndoAction(_sOldFunctionName,_sFunctionName,BROW_FUNCTION_ROW,_bListAction); + if ( !m_bVisibleRow[BROW_FUNCTION_ROW] ) + SetRowVisible(BROW_FUNCTION_ROW, sal_True); + RowModified(GetBrowseRow(BROW_FUNCTION_ROW), _nColumnId); +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::clearEntryFunctionField(const String& _sFieldName,OTableFieldDescRef& _pEntry,sal_Bool& _bListAction,USHORT _nColumnId) +{ + if ( isFieldNameAsterix( _sFieldName ) && (!_pEntry->isNoneFunction() || _pEntry->IsGroupBy()) ) + { + String sFunctionName; + GetFunctionName(SQL_TOKEN_COUNT,sFunctionName); + String sOldLocalizedFunctionName = _pEntry->GetFunction(); + if ( !sOldLocalizedFunctionName.Equals(sFunctionName) || _pEntry->IsGroupBy() ) + { + // append undo action for the function field + _pEntry->SetFunctionType(FKT_NONE); + _pEntry->SetFunction(::rtl::OUString()); + _pEntry->SetGroupBy(sal_False); + notifyFunctionFieldChanged(sOldLocalizedFunctionName,_pEntry->GetFunction(),_bListAction,_nColumnId); + } + } +} +// ----------------------------------------------------------------------------- +sal_Bool OSelectionBrowseBox::fillColumnRef(const OSQLParseNode* _pColumnRef, const Reference< XConnection >& _rxConnection, OTableFieldDescRef& _pEntry, sal_Bool& _bListAction ) +{ + OSL_ENSURE(_pColumnRef,"No valid parsenode!"); + ::rtl::OUString sColumnName,sTableRange; + OSQLParseTreeIterator::getColumnRange(_pColumnRef,_rxConnection,sColumnName,sTableRange); + return fillColumnRef(sColumnName,sTableRange,_rxConnection->getMetaData(),_pEntry,_bListAction); +} +// ----------------------------------------------------------------------------- +sal_Bool OSelectionBrowseBox::fillColumnRef(const ::rtl::OUString& _sColumnName,const ::rtl::OUString& _sTableRange,const Reference<XDatabaseMetaData>& _xMetaData,OTableFieldDescRef& _pEntry,sal_Bool& _bListAction) +{ + sal_Bool bError = sal_False; + ::comphelper::UStringMixEqual bCase(_xMetaData->supportsMixedCaseQuotedIdentifiers()); + // check if the table name is the same + if ( _sTableRange.getLength() && (bCase(_pEntry->GetTable(),_sTableRange) || bCase(_pEntry->GetAlias(),_sTableRange)) ) + { // a table was already inserted and the tables contains that column name + + if ( !_pEntry->GetTabWindow() ) + { // fill tab window + ::rtl::OUString sOldAlias = _pEntry->GetAlias(); + if ( !fillEntryTable(_pEntry,_pEntry->GetTable()) ) + fillEntryTable(_pEntry,_pEntry->GetAlias()); // only when the first failed + if ( !bCase(sOldAlias,_pEntry->GetAlias()) ) + notifyTableFieldChanged(sOldAlias,_pEntry->GetAlias(),_bListAction,GetCurColumnId()); + } + } + // check if the table window + OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(_pEntry->GetTabWindow()); + if ( !pEntryTab ) // no table found with this name so we have to travel through all tables + { + OJoinTableView::OTableWindowMap* pTabWinList = getDesignView()->getTableView()->GetTabWinMap(); + if ( pTabWinList ) + { + sal_uInt16 nTabCount = 0; + if ( !static_cast<OQueryTableView*>(getDesignView()->getTableView())->FindTableFromField(_sColumnName,_pEntry,nTabCount) ) // error occurred: column not in table window + { + String sErrorMsg(ModuleRes(RID_STR_FIELD_DOESNT_EXIST)); + sErrorMsg.SearchAndReplaceAscii("$name$",_sColumnName); + OSQLWarningBox( this, sErrorMsg ).Execute(); + bError = sal_True; + } + else + { + pEntryTab = static_cast<OQueryTableWindow*>(_pEntry->GetTabWindow()); + notifyTableFieldChanged(String(),_pEntry->GetAlias(),_bListAction,GetCurColumnId()); + } + } + } + if ( pEntryTab ) // here we got a valid table + _pEntry->SetField(_sColumnName); + + return bError; +} +// ----------------------------------------------------------------------------- +sal_Bool OSelectionBrowseBox::saveField(const String& _sFieldName,OTableFieldDescRef& _pEntry,sal_Bool& _bListAction) +{ + sal_Bool bError = sal_False; + + OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController()); + + // first look if the name can be found in our tables + sal_uInt16 nTabCount = 0; + String sOldAlias = _pEntry->GetAlias(); + if ( static_cast<OQueryTableView*>(getDesignView()->getTableView())->FindTableFromField(_sFieldName,_pEntry,nTabCount) ) + { + // append undo action for the alias name + _pEntry->SetField(_sFieldName); + notifyTableFieldChanged(sOldAlias,_pEntry->GetAlias(),_bListAction,GetCurColumnId()); + clearEntryFunctionField(_sFieldName,_pEntry,_bListAction,_pEntry->GetColumnId()); + return bError; + } + + Reference<XConnection> xConnection( rController.getConnection() ); + Reference< XDatabaseMetaData > xMetaData; + if ( xConnection.is() ) + xMetaData = xConnection->getMetaData(); + OSL_ENSURE( xMetaData.is(), "OSelectionBrowseBox::saveField: invalid connection/meta data!" ); + if ( !xMetaData.is() ) + return sal_True; + + ::rtl::OUString sErrorMsg; + // second test if the name can be set as select columns in a pseudo statement + // we have to look which entries we should quote + + const ::rtl::OUString sFieldAlias = _pEntry->GetFieldAlias(); + size_t nPass = 4; + ::connectivity::OSQLParser& rParser( rController.getParser() ); + OSQLParseNode* pParseNode = NULL; + // 4 passes in trying to interprete the field name + // - don't quote the field name, parse internationally + // - don't quote the field name, parse en-US + // - quote the field name, parse internationally + // - quote the field name, parse en-US + do + { + bool bQuote = ( nPass <= 2 ); + bool bInternational = ( nPass % 2 ) == 0; + + ::rtl::OUString sSql; + if ( bQuote ) + sSql += ::dbtools::quoteName( xMetaData->getIdentifierQuoteString(), _sFieldName ); + else + sSql += _sFieldName; + + if ( _pEntry->isAggreateFunction() ) + { + DBG_ASSERT(_pEntry->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-("); + ::rtl::OUStringBuffer aTmpStr2( _pEntry->GetFunction()); + aTmpStr2.appendAscii("("); + aTmpStr2.append(sSql); + aTmpStr2.appendAscii(")"); + sSql = aTmpStr2.makeStringAndClear(); + } + + sSql = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT ")) + sSql; + if ( sFieldAlias.getLength() ) + { // always quote the alias name there canbe no function in it + sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ")); + sSql += ::dbtools::quoteName( xMetaData->getIdentifierQuoteString(), sFieldAlias ); + } + sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM x")); + + pParseNode = rParser.parseTree( sErrorMsg, sSql, bInternational ); + } + while ( ( pParseNode == NULL ) && ( --nPass > 0 ) ); + + if ( pParseNode == NULL ) + { + // something different which we have to check (may be a select statement) + String sErrorMessage( ModuleRes( STR_QRY_COLUMN_NOT_FOUND ) ); + sErrorMessage.SearchAndReplaceAscii("$name$",_sFieldName); + OSQLWarningBox( this, sErrorMessage ).Execute(); + return sal_True; + } + + // we got a valid select column + // find what type of column has be inserted + ::connectivity::OSQLParseNode* pSelection = pParseNode->getChild(2); + if ( SQL_ISRULE(pSelection,selection) ) // we found the asterix + { + _pEntry->SetField(_sFieldName); + clearEntryFunctionField(_sFieldName,_pEntry,_bListAction,_pEntry->GetColumnId()); + } // travel through the select column parse node + else + { + ::comphelper::UStringMixEqual bCase(xMetaData->supportsMixedCaseQuotedIdentifiers()); + + OTableFieldDescRef aSelEntry = _pEntry; + USHORT nColumnId = aSelEntry->GetColumnId(); + + sal_uInt32 nCount = pSelection->count(); + for (sal_uInt32 i = 0; i < nCount; ++i) + { + if ( i > 0 ) // may we have to append more than one field + { + USHORT nColumnPostion; + aSelEntry = FindFirstFreeCol(nColumnPostion); + if ( !aSelEntry.is() ) + { + AppendNewCol(1); + aSelEntry = FindFirstFreeCol(nColumnPostion); + } + ++nColumnPostion; + nColumnId = GetColumnId(nColumnPostion); + } + + ::connectivity::OSQLParseNode* pChild = pSelection->getChild( i ); + OSL_ENSURE(SQL_ISRULE(pChild,derived_column), "No derived column found!"); + // get the column alias + ::rtl::OUString sColumnAlias = OSQLParseTreeIterator::getColumnAlias(pChild); + if ( sColumnAlias.getLength() ) // we found an as clause + { + String aSelectionAlias = aSelEntry->GetFieldAlias(); + aSelEntry->SetFieldAlias( sColumnAlias ); + // append undo + appendUndoAction(aSelectionAlias,aSelEntry->GetFieldAlias(),BROW_COLUMNALIAS_ROW,_bListAction); + if ( m_bVisibleRow[BROW_COLUMNALIAS_ROW] ) + RowModified(GetBrowseRow(BROW_COLUMNALIAS_ROW), nColumnId); + } + + ::connectivity::OSQLParseNode* pColumnRef = pChild->getChild(0); + if ( + pColumnRef->count() == 3 && + SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") && + SQL_ISPUNCTUATION(pColumnRef->getChild(2),")") + ) + pColumnRef = pColumnRef->getChild(1); + + if ( SQL_ISRULE(pColumnRef,column_ref) ) // we found a valid column name or more column names + { + // look if we can find the corresponding table + bError = fillColumnRef( pColumnRef, xConnection, aSelEntry, _bListAction ); + + // we found a simple column so we must clear the function fields but only when the column name is '*' + // and the function is different to count + clearEntryFunctionField(_sFieldName,aSelEntry,_bListAction,nColumnId); + } + else + { + // first check if we have a aggregate function and only a function + if ( SQL_ISRULE(pColumnRef,general_set_fct) ) + { + String sLocalizedFunctionName; + if ( GetFunctionName(pColumnRef->getChild(0)->getTokenID(),sLocalizedFunctionName) ) + { + String sOldLocalizedFunctionName = aSelEntry->GetFunction(); + aSelEntry->SetFunction(sLocalizedFunctionName); + sal_uInt32 nFunCount = pColumnRef->count() - 1; + sal_Int32 nFunctionType = FKT_AGGREGATE; + sal_Bool bQuote = sal_False; + // may be there exists only one parameter which is a column, fill all information into our fields + if ( nFunCount == 4 && SQL_ISRULE(pColumnRef->getChild(3),column_ref) ) + bError = fillColumnRef( pColumnRef->getChild(3), xConnection, aSelEntry, _bListAction ); + else if ( nFunCount == 3 ) // we have a COUNT(*) here, so take the first table + bError = fillColumnRef( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), ::rtl::OUString(), xMetaData, aSelEntry, _bListAction ); + else + { + nFunctionType |= FKT_NUMERIC; + bQuote = sal_True; + aSelEntry->SetDataType(DataType::DOUBLE); + aSelEntry->SetFieldType(TAB_NORMAL_FIELD); + } + + // now parse the parameters + ::rtl::OUString sParameters; + for(sal_uInt32 function = 2; function < nFunCount; ++function) // we only want to parse the parameters of the function + pColumnRef->getChild(function)->parseNodeToStr( sParameters, xConnection, &rParser.getContext(), sal_True, bQuote ); + + aSelEntry->SetFunctionType(nFunctionType); + aSelEntry->SetField(sParameters); + if ( aSelEntry->IsGroupBy() ) + { + sOldLocalizedFunctionName = m_aFunctionStrings.GetToken(m_aFunctionStrings.GetTokenCount()-1); + aSelEntry->SetGroupBy(sal_False); + } + + // append undo action + notifyFunctionFieldChanged(sOldLocalizedFunctionName,sLocalizedFunctionName,_bListAction, nColumnId); + } + else + OSL_ENSURE(0,"Unsupported function inserted!"); + + } + else + { + // so we first clear the function field + clearEntryFunctionField(_sFieldName,aSelEntry,_bListAction,nColumnId); + ::rtl::OUString sFunction; + pColumnRef->parseNodeToStr( sFunction, + xConnection, + &rController.getParser().getContext(), + sal_True, + sal_True); // quote is to true because we need quoted elements inside the function + + getDesignView()->fillFunctionInfo(pColumnRef,sFunction,aSelEntry); + + if( SQL_ISRULEOR2(pColumnRef,position_exp,extract_exp) || + SQL_ISRULEOR2(pColumnRef,fold,char_substring_fct) || + SQL_ISRULEOR2(pColumnRef,length_exp,char_value_fct) ) + // a calculation has been found ( can be calc and function ) + { + // now parse the whole statement + sal_uInt32 nFunCount = pColumnRef->count(); + ::rtl::OUString sParameters; + for(sal_uInt32 function = 0; function < nFunCount; ++function) + pColumnRef->getChild(function)->parseNodeToStr( sParameters, xConnection, &rParser.getContext(), sal_True, sal_True ); + + sOldAlias = aSelEntry->GetAlias(); + sal_Int32 nNewFunctionType = aSelEntry->GetFunctionType() | FKT_NUMERIC | FKT_OTHER; + aSelEntry->SetFunctionType(nNewFunctionType); + aSelEntry->SetField(sParameters); + } + else + { + aSelEntry->SetFieldAlias(sColumnAlias); + if ( SQL_ISRULE(pColumnRef,set_fct_spec) ) + aSelEntry->SetFunctionType(/*FKT_NUMERIC | */FKT_OTHER); + else + { + if ( SQL_ISRULEOR2(pColumnRef,num_value_exp,term) || SQL_ISRULE(pColumnRef,factor) ) + aSelEntry->SetDataType(DataType::DOUBLE); + else if ( SQL_ISRULE(pColumnRef,value_exp) ) + aSelEntry->SetDataType(DataType::TIMESTAMP); + else + aSelEntry->SetDataType(DataType::VARCHAR); + aSelEntry->SetFunctionType(FKT_NUMERIC | FKT_OTHER); + } + } + + aSelEntry->SetAlias(::rtl::OUString()); + notifyTableFieldChanged(sOldAlias,aSelEntry->GetAlias(),_bListAction, nColumnId); + } + + } + if ( i > 0 && !InsertField(aSelEntry,BROWSER_INVALIDID,sal_True,sal_False).is() ) // may we have to append more than one field + { // the field could not be isnerted + String sErrorMessage( ModuleRes( RID_STR_FIELD_DOESNT_EXIST ) ); + sErrorMessage.SearchAndReplaceAscii("$name$",aSelEntry->GetField()); + OSQLWarningBox( this, sErrorMessage ).Execute(); + bError = sal_True; + } + } + } + delete pParseNode; + + return bError; +} +//------------------------------------------------------------------------------ +sal_Bool OSelectionBrowseBox::SaveModified() +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController()); + OTableFieldDescRef pEntry = NULL; + USHORT nCurrentColumnPos = GetColumnPos(GetCurColumnId()); + if(getFields().size() > static_cast<USHORT>(nCurrentColumnPos - 1)) + pEntry = getEntry(nCurrentColumnPos - 1); + + sal_Bool bWasEmpty = pEntry.is() ? pEntry->IsEmpty() : sal_False; + sal_Bool bError = sal_False; + sal_Bool bListAction = sal_False; + + if (pEntry.is() && Controller().Is() && Controller()->IsModified()) + { + // fuer die Undo-Action + String strOldCellContents,sNewValue; + long nRow = GetRealRow(GetCurRow()); + sal_Bool bAppendRow = sal_False; + switch (nRow) + { + case BROW_VIS_ROW: + { + sal_Bool bOldValue = m_pVisibleCell->GetBox().GetSavedValue() != STATE_NOCHECK; + strOldCellContents = bOldValue ? g_strOne : g_strZero; + sNewValue = !bOldValue ? g_strOne : g_strZero; + } + if((m_bOrderByUnRelated || pEntry->GetOrderDir() == ORDER_NONE) && + (m_bGroupByUnRelated || !pEntry->IsGroupBy())) + { + pEntry->SetVisible(m_pVisibleCell->GetBox().IsChecked()); + } + else + { + pEntry->SetVisible(sal_True); + m_pVisibleCell->GetBox().Check(); + } + break; + + case BROW_FIELD_ROW: + { + String aFieldName(m_pFieldCell->GetText()); + try + { + if (!aFieldName.Len()) + { + OTableFieldDescRef pNewEntry = new OTableFieldDesc(); + pNewEntry->SetColumnId( pEntry->GetColumnId() ); + ::std::replace(getFields().begin(),getFields().end(),pEntry,pNewEntry); + sal_uInt16 nCol = GetCurColumnId(); + for (int i = 0; i < m_nVisibleCount; i++) // Spalte neu zeichnen + RowModified(i,nCol); + } + else + { + strOldCellContents = pEntry->GetField(); + bListAction = sal_True; + if ( !m_bInUndoMode ) + rController.getUndoMgr()->EnterListAction(String(),String()); + + USHORT nPos = m_pFieldCell->GetEntryPos(aFieldName); + String aAliasName = pEntry->GetAlias(); + if ( nPos != COMBOBOX_ENTRY_NOTFOUND && !aAliasName.Len() && aFieldName.GetTokenCount('.') > 1 ) + { // special case, we have a table field so we must cut the table name + String sTableAlias = aFieldName.GetToken(0,'.'); + pEntry->SetAlias(sTableAlias); + String sColumnName = aFieldName.Copy(sTableAlias.Len()+1,aFieldName.Len() - sTableAlias.Len() -1); + Reference<XConnection> xConnection = rController.getConnection(); + if ( !xConnection.is() ) + return sal_False; + bError = fillColumnRef( sColumnName, sTableAlias, xConnection->getMetaData(), pEntry, bListAction ); + } + else + bError = sal_True; + + if ( bError ) + bError = saveField(aFieldName,pEntry,bListAction); + } + } + catch(Exception&) + { + bError = sal_True; + } + if ( bError ) + { + sNewValue = aFieldName; + if ( !m_bInUndoMode ) + static_cast<OQueryController&>(getDesignView()->getController()).getUndoMgr()->LeaveListAction(); + bListAction = sal_False; + } + else + sNewValue = pEntry->GetField(); + rController.InvalidateFeature( ID_BROWSER_QUERY_EXECUTE ); + } + break; + + case BROW_TABLE_ROW: + { + String aAliasName = m_pTableCell->GetSelectEntry(); + strOldCellContents = pEntry->GetAlias(); + if ( m_pTableCell->GetSelectEntryPos() != 0 ) + { + pEntry->SetAlias(aAliasName); + // we have to set the table name as well as the table window + OJoinTableView::OTableWindowMap* pTabWinList = getDesignView()->getTableView()->GetTabWinMap(); + if (pTabWinList) + { + OJoinTableView::OTableWindowMapIterator aIter = pTabWinList->find(aAliasName); + if(aIter != pTabWinList->end()) + { + OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(aIter->second); + if (pEntryTab) + { + pEntry->SetTable(pEntryTab->GetTableName()); + pEntry->SetTabWindow(pEntryTab); + } + } + } + } + else + { + pEntry->SetAlias(::rtl::OUString()); + pEntry->SetTable(::rtl::OUString()); + pEntry->SetTabWindow(NULL); + } + sNewValue = pEntry->GetAlias(); + + } break; + + case BROW_ORDER_ROW: + { + strOldCellContents = String::CreateFromInt32((sal_uInt16)pEntry->GetOrderDir()); + sal_uInt16 nIdx = m_pOrderCell->GetSelectEntryPos(); + if (nIdx == sal_uInt16(-1)) + nIdx = 0; + pEntry->SetOrderDir(EOrderDir(nIdx)); + if(!m_bOrderByUnRelated) + { + pEntry->SetVisible(sal_True); + m_pVisibleCell->GetBox().Check(); + RowModified(GetBrowseRow(BROW_VIS_ROW), GetCurColumnId()); + } + sNewValue = String::CreateFromInt32((sal_uInt16)pEntry->GetOrderDir()); + } break; + + case BROW_COLUMNALIAS_ROW: + strOldCellContents = pEntry->GetFieldAlias(); + pEntry->SetFieldAlias(m_pTextCell->GetText()); + sNewValue = pEntry->GetFieldAlias(); + break; + case BROW_FUNCTION_ROW: + { + strOldCellContents = pEntry->GetFunction(); + sal_uInt16 nPos = m_pFunctionCell->GetSelectEntryPos(); + // Diese Funktionen stehen nur unter CORE zur Verfügung + String sFunctionName = m_pFunctionCell->GetEntry(nPos); + String sGroupFunctionName = m_aFunctionStrings.GetToken(m_aFunctionStrings.GetTokenCount()-1); + sal_Bool bGroupBy = sal_False; + if ( sGroupFunctionName.Equals(sFunctionName) ) // check if the function name is GROUP + { + bGroupBy = sal_True; + + if ( !m_bGroupByUnRelated && !pEntry->IsVisible() ) + { + // we have to change the visblie flag, so we must append also an undo action + pEntry->SetVisible(sal_True); + m_pVisibleCell->GetBox().Check(); + appendUndoAction(g_strZero,g_strOne,BROW_VIS_ROW,bListAction); + RowModified(GetBrowseRow(BROW_VIS_ROW), GetCurColumnId()); + } + + pEntry->SetFunction(String()); + pEntry->SetFunctionType(pEntry->GetFunctionType() & ~FKT_AGGREGATE ); + } + else if ( nPos ) // we found an aggregate function + { + pEntry->SetFunctionType(pEntry->GetFunctionType() | FKT_AGGREGATE ); + pEntry->SetFunction(sFunctionName); + } + else + { + sFunctionName = String(); + pEntry->SetFunction(String()); + pEntry->SetFunctionType(pEntry->GetFunctionType() & ~FKT_AGGREGATE ); + } + + pEntry->SetGroupBy(bGroupBy); + + sNewValue = sFunctionName; + } + break; + default: + { + Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); + if(!xConnection.is()) + break; + + sal_uInt16 nIdx = sal_uInt16(nRow - BROW_CRIT1_ROW); + String aText = m_pTextCell->GetText(); + + aText.EraseLeadingChars(); + ::rtl::OUString aCrit; + if(aText.Len()) + { + ::rtl::OUString aErrorMsg; + Reference<XPropertySet> xColumn; + OSQLParseNode* pParseNode = getDesignView()->getPredicateTreeFromEntry(pEntry,aText,aErrorMsg,xColumn); + + if (pParseNode) + { + pParseNode->parseNodeToPredicateStr(aCrit, + xConnection, + static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(), + xColumn, + getDesignView()->getLocale(), + static_cast<sal_Char>(getDesignView()->getDecimalSeparator().toChar()), + &(static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext())); + delete pParseNode; + } + else + { + if(xColumn.is()) + { + sal_Int32 nType = 0; + xColumn->getPropertyValue(PROPERTY_TYPE) >>= nType; + switch(nType) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + case DataType::CLOB: + if(aText.GetChar(0) != '\'' || aText.GetChar(aText.Len() -1) != '\'') + { + aText.SearchAndReplaceAll(String::CreateFromAscii("'"),String::CreateFromAscii("''")); + String aTmp(String::CreateFromAscii("'")); + (aTmp += aText) += String::CreateFromAscii("'"); + aText = aTmp; + } + break; + default: + ; + } + ::connectivity::OSQLParser& rParser = static_cast<OQueryController&>(getDesignView()->getController()).getParser(); + pParseNode = rParser.predicateTree(aErrorMsg, + aText, + static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(), + xColumn); + if (pParseNode) + { + pParseNode->parseNodeToPredicateStr(aCrit, + xConnection, + static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(), + xColumn, + getDesignView()->getLocale(), + static_cast<sal_Char>(getDesignView()->getDecimalSeparator().toChar()), + &(static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext())); + delete pParseNode; + } + else + { + if ( !m_bDisableErrorBox ) + { + OSQLWarningBox( this, aErrorMsg ).Execute(); + } + bError = sal_True; + } + } + else + { + if ( !m_bDisableErrorBox ) + { + OSQLWarningBox( this, aErrorMsg ).Execute(); + } + bError = sal_True; + } + } + } + strOldCellContents = pEntry->GetCriteria(nIdx); + pEntry->SetCriteria(nIdx, aCrit); + sNewValue = pEntry->GetCriteria(nIdx); + if(aCrit.getLength() && nRow >= (GetRowCount()-1)) + bAppendRow = sal_True; + } + } + if(!bError && Controller()) + Controller()->ClearModified(); + + RowModified(GetCurRow(), GetCurColumnId()); + + if ( bAppendRow ) + { + RowInserted( GetRowCount()-1, 1, TRUE ); + m_bVisibleRow.push_back(sal_True); + ++m_nVisibleCount; + } + + if(!bError) + { + // und noch die Undo-Action fuer das Ganze + appendUndoAction(strOldCellContents,sNewValue,nRow); + + } + } + + // habe ich Daten in einer FieldDescription gespeichert, die vorher leer war und es nach den Aenderungen nicht mehr ist ? + if ( pEntry.is() && bWasEmpty && !pEntry->IsEmpty() && !bError ) + { + // Default auf sichtbar + pEntry->SetVisible(sal_True); + appendUndoAction(g_strZero,g_strOne,BROW_VIS_ROW,bListAction); + RowModified(BROW_VIS_ROW, GetCurColumnId()); + + // wenn noetig neue freie Spalten anlegen + USHORT nDummy; + CheckFreeColumns(nDummy); + } + + if ( bListAction && !m_bInUndoMode ) + static_cast<OQueryController&>(getDesignView()->getController()).getUndoMgr()->LeaveListAction(); + + return pEntry != NULL && !bError; +} + +//------------------------------------------------------------------------------ +sal_Bool OSelectionBrowseBox::SeekRow(long nRow) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + sal_Bool bRet = sal_False; + + m_nSeekRow = nRow; + if (nRow < m_nVisibleCount ) + bRet = sal_True; + + return bRet; +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::PaintCell(OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColumnId) const +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + rDev.SetClipRegion( rRect ); + + OTableFieldDescRef pEntry = NULL; + USHORT nPos = GetColumnPos(nColumnId); + if(getFields().size() > sal_uInt16(nPos - 1)) + pEntry = getFields()[nPos - 1]; + + if (!pEntry.is()) + return; + + long nRow = GetRealRow(m_nSeekRow); + if (nRow == BROW_VIS_ROW) + PaintTristate(rDev, rRect, pEntry->IsVisible() ? STATE_CHECK : STATE_NOCHECK); + else + rDev.DrawText(rRect, GetCellText(nRow, nColumnId),TEXT_DRAW_VCENTER); + + rDev.SetClipRegion( ); +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::PaintStatusCell(OutputDevice& rDev, const Rectangle& rRect) const +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + Rectangle aRect(rRect); + aRect.TopLeft().Y() -= 2; + String aLabel(ModuleRes(STR_QUERY_HANDLETEXT)); + + // ab BROW_CRIT2_ROW werden alle Zeilen mit "oder" angegeben + xub_StrLen nToken = (xub_StrLen) (m_nSeekRow >= GetBrowseRow(BROW_CRIT2_ROW)) + ? + xub_StrLen(BROW_CRIT2_ROW) : xub_StrLen(GetRealRow(m_nSeekRow)); + rDev.DrawText(aRect, aLabel.GetToken(nToken),TEXT_DRAW_VCENTER); +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::RemoveColumn(USHORT _nColumnId) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController()); + + USHORT nPos = GetColumnPos(_nColumnId); + // das Control sollte immer genau eine Spalte mehr haben, naemlich die HandleColumn + DBG_ASSERT((nPos == 0) || (nPos <= getFields().size()), "OSelectionBrowseBox::RemoveColumn : invalid parameter nColId"); + // ColId ist bei mir gleichbedeutend mit Position, und da sollte die Bedingung natuerlich zutreffen + + sal_uInt16 nCurCol = GetCurColumnId(); + long nCurrentRow = GetCurRow(); + + DeactivateCell(); + + getFields().erase( getFields().begin() + (nPos - 1) ); + OTableFieldDescRef pEntry = new OTableFieldDesc(); + pEntry->SetColumnId(_nColumnId); + getFields().push_back(pEntry); + + EditBrowseBox::RemoveColumn( _nColumnId ); + InsertDataColumn( _nColumnId , String(), DEFAULT_SIZE, HIB_STDSTYLE, HEADERBAR_APPEND); + + // Neuzeichnen + Rectangle aInvalidRect = GetInvalidRect( _nColumnId ); + Invalidate( aInvalidRect ); + + ActivateCell( nCurrentRow, nCurCol ); + + rController.setModified( sal_True ); + + invalidateUndoRedo(); +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::RemoveField(sal_uInt16 nColumnId ) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController()); + + USHORT nPos = GetColumnPos(nColumnId); + OSL_ENSURE(getFields().size() > sal_uInt16(nPos-1),"ID is to great!"); + + OTableFieldDescRef pDesc = getEntry((sal_uInt32)(nPos - 1)) ; + pDesc->SetColWidth( (sal_uInt16)GetColumnWidth(nColumnId) ); // hat er sich vorher leider nicht gemerkt + + // UndoAction erzeugen + if ( !m_bInUndoMode ) + { + OTabFieldDelUndoAct* pUndoAction = new OTabFieldDelUndoAct( this ); + pUndoAction->SetTabFieldDescr(pDesc); + pUndoAction->SetColumnPosition(nPos); + rController.addUndoActionAndInvalidate( pUndoAction ); + } + + RemoveColumn(nColumnId); + + invalidateUndoRedo(); +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::adjustSelectionMode( sal_Bool _bClickedOntoHeader, sal_Bool _bClickedOntoHandleCol ) +{ + // wenn ein Header selectiert wird, muß die selection angezeigt werden, sonst nicht) + if ( _bClickedOntoHeader ) + { + if (0 == GetSelectColumnCount() ) + // wenn es schon eine selektierte Spalte gibt, bin ich schon im richtigen Modus + if ( BROWSER_HIDESELECT == ( m_nMode & BROWSER_HIDESELECT ) ) + { + m_nMode &= ~BROWSER_HIDESELECT; + m_nMode |= BROWSER_MULTISELECTION; + SetMode( m_nMode ); + } + } + else if ( BROWSER_HIDESELECT != ( m_nMode & BROWSER_HIDESELECT ) ) + { + if ( GetSelectColumnCount() != 0 ) + SetNoSelection(); + + if ( _bClickedOntoHandleCol ) + { + m_nMode |= BROWSER_HIDESELECT; + m_nMode &= ~BROWSER_MULTISELECTION; + SetMode( m_nMode ); + } + } +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::MouseButtonDown(const BrowserMouseEvent& rEvt) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + if( rEvt.IsLeft() ) + { + sal_Bool bOnHandle = HANDLE_ID == rEvt.GetColumnId(); + sal_Bool bOnHeader = ( rEvt.GetRow() < 0 ) && !bOnHandle; + adjustSelectionMode( bOnHeader, bOnHandle ); + } + EditBrowseBox::MouseButtonDown(rEvt); +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::MouseButtonUp(const BrowserMouseEvent& rEvt) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + EditBrowseBox::MouseButtonUp( rEvt ); + static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( ID_BROWSER_QUERY_EXECUTE ); +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::KeyInput( const KeyEvent& rEvt ) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + if (IsColumnSelected(GetCurColumnId())) + { + if (rEvt.GetKeyCode().GetCode() == KEY_DELETE && // Delete rows + !rEvt.GetKeyCode().IsShift() && + !rEvt.GetKeyCode().IsMod1()) + { + RemoveField(GetCurColumnId()); + return; + } + } + EditBrowseBox::KeyInput(rEvt); +} + + +//------------------------------------------------------------------------------ +sal_Int8 OSelectionBrowseBox::AcceptDrop( const BrowserAcceptDropEvent& rEvt ) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + sal_Int8 nDropAction = DND_ACTION_NONE; + if ( rEvt.GetRow() >= -1 ) + { + if ( IsEditing() ) + { + // #100271# OJ allow the asterix again + m_bDisableErrorBox = sal_True; + SaveModified(); + m_bDisableErrorBox = sal_False; + DeactivateCell(); + } + // check if the format is already supported, if not deactivate the current cell and try again + if ( OJoinExchObj::isFormatAvailable(GetDataFlavors()) ) + nDropAction = DND_ACTION_LINK; + } + + return nDropAction; +} + +//------------------------------------------------------------------------------ +sal_Int8 OSelectionBrowseBox::ExecuteDrop( const BrowserExecuteDropEvent& _rEvt ) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + + TransferableDataHelper aDropped(_rEvt.maDropEvent.Transferable); + if (!OJoinExchObj::isFormatAvailable(aDropped.GetDataFlavorExVector())) + { + DBG_ERROR("OSelectionBrowseBox::ExecuteDrop: this should never have passed AcceptDrop!"); + return DND_ACTION_NONE; + } + + OTableFieldDesc aInfo; + // Einfuegen des Feldes an der gewuenschten Position + OJoinExchangeData jxdSource = OJoinExchObj::GetSourceDescription(_rEvt.maDropEvent.Transferable); + InsertField(jxdSource); + + return DND_ACTION_LINK; +} + +//------------------------------------------------------------------------------ +OTableFieldDescRef OSelectionBrowseBox::AppendNewCol( sal_uInt16 nCnt) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + // es koennen mehrere angelegt werden, aber der Erste + // wird returnt + sal_uInt32 nCount = getFields().size(); + for (sal_uInt16 i=0 ; i<nCnt ; i++) + { + OTableFieldDescRef pEmptyEntry = new OTableFieldDesc(); + getFields().push_back(pEmptyEntry); + USHORT nColumnId = sal::static_int_cast< USHORT >(getFields().size()); + pEmptyEntry->SetColumnId( nColumnId ); + + InsertDataColumn( nColumnId , String(), DEFAULT_SIZE, HIB_STDSTYLE, HEADERBAR_APPEND); + } + + return getFields()[nCount]; +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::DeleteFields(const String& rAliasName) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + if (!getFields().empty()) + { + sal_uInt16 nColId = GetCurColumnId(); + sal_uInt32 nRow = GetCurRow(); + + sal_Bool bWasEditing = IsEditing(); + if (bWasEditing) + DeactivateCell(); + + OTableFields::reverse_iterator aIter = getFields().rbegin(); + OTableFieldDescRef pEntry = NULL; + for(USHORT nPos=sal::static_int_cast< USHORT >(getFields().size());aIter != getFields().rend();++aIter,--nPos) + { + pEntry = *aIter; + if ( pEntry->GetAlias().equals( rAliasName ) ) + { + RemoveField( GetColumnId( nPos ) ); + break; + } + } + + if (bWasEditing) + ActivateCell(nRow , nColId); + } +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::SetColWidth(sal_uInt16 nColId, long nNewWidth) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + sal_Bool bWasEditing = IsEditing(); + if (bWasEditing) + DeactivateCell(); + + // die Basisklasse machen lassen + SetColumnWidth(nColId, nNewWidth); + + // der FieldDescription Bescheid sagen + OTableFieldDescRef pEntry = getEntry(GetColumnPos(nColId) - 1); + if (pEntry.is()) + pEntry->SetColWidth(sal_uInt16(GetColumnWidth(nColId))); + + if (bWasEditing) + ActivateCell(GetCurRow(), GetCurColumnId()); +} + +//------------------------------------------------------------------------------ +Rectangle OSelectionBrowseBox::GetInvalidRect( sal_uInt16 nColId ) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + ////////////////////////////////////////////////////////////////////// + // Rechteck ist erst einmal der gesamte Outputbereich des Fensters + Rectangle aInvalidRect( Point(0,0), GetOutputSizePixel() ); + + ////////////////////////////////////////////////////////////////////// + // Dann wird die linke Seite angepasst + Rectangle aFieldRect(GetCellRect( 0, nColId )); // used instead of GetFieldRectPixel + aInvalidRect.Left() = aFieldRect.Left(); + + return aInvalidRect; +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::InsertColumn(OTableFieldDescRef pEntry, USHORT& _nColumnPostion) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + // das Control sollte immer genau eine Spalte mehr haben, naemlich die HandleColumn + DBG_ASSERT(_nColumnPostion == BROWSER_INVALIDID || (_nColumnPostion <= (long)getFields().size()), "OSelectionBrowseBox::InsertColumn : invalid parameter nColId."); + // -1 heisst ganz hinten, Count heisst ganz hinten, der Rest bezeichnet eine richtige Position + + sal_uInt16 nCurCol = GetCurColumnId(); + long nCurrentRow = GetCurRow(); + + DeactivateCell(); + + // remember the column id of the current positon + USHORT nColumnId = GetColumnId(_nColumnPostion); + // Wenn zu klein oder zu gross, auf Ende der Liste setzen + if ((_nColumnPostion == BROWSER_INVALIDID) || (_nColumnPostion >= getFields().size())) // Anhaengen des Feldes + { + if (FindFirstFreeCol(_nColumnPostion) == NULL) // keine freie Column mehr + { + AppendNewCol(1); + _nColumnPostion = sal::static_int_cast< USHORT >( + getFields().size()); + } + else + ++_nColumnPostion; // innerhalb der vorgegebenen Liste + nColumnId = GetColumnId(_nColumnPostion); + pEntry->SetColumnId( nColumnId ); + getFields()[ _nColumnPostion - 1] = pEntry; + } + + // check if the column ids are identical, if not we have to move + if ( pEntry->GetColumnId() != nColumnId ) + { + USHORT nOldPosition = GetColumnPos(pEntry->GetColumnId()); + OSL_ENSURE( nOldPosition != 0,"Old position was 0. Not possible!"); + SetColumnPos(pEntry->GetColumnId(),_nColumnPostion); + // we have to delete an empty field for the fields list, because the columns must have equal length + if ( nOldPosition > 0 && nOldPosition <= getFields().size() ) + getFields()[nOldPosition - 1] = pEntry; + + ColumnMoved(pEntry->GetColumnId(),FALSE); + } + + if ( pEntry->GetFunctionType() & (FKT_AGGREGATE) ) + { + String sFunctionName = pEntry->GetFunction(); + if ( GetFunctionName(sal_uInt32(-1),sFunctionName) ) + pEntry->SetFunction(sFunctionName); + } + + nColumnId = pEntry->GetColumnId(); + + SetColWidth(nColumnId,getDesignView()->getColWidth(GetColumnPos(nColumnId)-1)); + // Neuzeichnen + Rectangle aInvalidRect = GetInvalidRect( nColumnId ); + Invalidate( aInvalidRect ); + + ActivateCell( nCurrentRow, nCurCol ); + static_cast<OQueryController&>(getDesignView()->getController()).setModified( sal_True ); + + invalidateUndoRedo(); +} + +//------------------------------------------------------------------------------ +OTableFieldDescRef OSelectionBrowseBox::InsertField(const OJoinExchangeData& jxdSource, USHORT _nColumnPostion, sal_Bool bVis, sal_Bool bActivate) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + OQueryTableWindow* pSourceWin = static_cast<OQueryTableWindow*>(jxdSource.pListBox->GetTabWin()); + if (!pSourceWin) + return NULL; + + // Namen/Position des selektierten Feldes + String aFieldName = jxdSource.pListBox->GetEntryText(jxdSource.pEntry); + sal_uInt32 nFieldIndex = jxdSource.pListBox->GetModel()->GetAbsPos(jxdSource.pEntry); + OTableFieldInfo* pInf = static_cast<OTableFieldInfo*>(jxdSource.pEntry->GetUserData()); + + // eine DragInfo aufbauen, damit ich mich auf das andere InsertField zurueckziehen kann + OTableFieldDescRef aInfo = new OTableFieldDesc(pSourceWin->GetTableName(),aFieldName); + aInfo->SetTabWindow(pSourceWin); + aInfo->SetFieldIndex(nFieldIndex); + aInfo->SetFieldType(pInf->GetKeyType()); + aInfo->SetAlias(pSourceWin->GetAliasName()); + + aInfo->SetDataType(pInf->GetDataType()); + aInfo->SetVisible(bVis); + + return InsertField(aInfo, _nColumnPostion, bVis, bActivate); +} + +//------------------------------------------------------------------------------ +OTableFieldDescRef OSelectionBrowseBox::InsertField(const OTableFieldDescRef& _rInfo, USHORT _nColumnPostion, sal_Bool bVis, sal_Bool bActivate) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + + if(m_nMaxColumns && m_nMaxColumns <= FieldsCount()) + return NULL; + if (bActivate) + SaveModified(); + + // Neue Spaltenbeschreibung + OTableFieldDescRef pEntry = _rInfo; + pEntry->SetVisible(bVis); + + // Spalte einfuegen + InsertColumn( pEntry, _nColumnPostion ); + + if ( !m_bInUndoMode ) + { + // UndoAction erzeugen + OTabFieldCreateUndoAct* pUndoAction = new OTabFieldCreateUndoAct( this ); + pUndoAction->SetTabFieldDescr( pEntry ); + pUndoAction->SetColumnPosition(_nColumnPostion); + getDesignView()->getController().addUndoActionAndInvalidate( pUndoAction ); + } + + return pEntry; +} + +//------------------------------------------------------------------------------ +sal_uInt16 OSelectionBrowseBox::FieldsCount() +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + OTableFields::iterator aIter = getFields().begin(); + sal_uInt16 nCount = 0; + + while (aIter != getFields().end()) + { + if ((*aIter).is() && !(*aIter)->IsEmpty()) + ++nCount; + ++aIter; + } + + return nCount; +} + +//------------------------------------------------------------------------------ +OTableFieldDescRef OSelectionBrowseBox::FindFirstFreeCol(USHORT& _rColumnPosition ) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + OTableFields::iterator aIter = getFields().begin(); + OTableFields::iterator aEnd = getFields().end(); + + _rColumnPosition = BROWSER_INVALIDID; + + while ( aIter != aEnd ) + { + ++_rColumnPosition; + OTableFieldDescRef pEntry = (*aIter); + if ( pEntry.is() && pEntry->IsEmpty() ) + return pEntry; + ++aIter; + } + + return NULL; +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::CheckFreeColumns(USHORT& _rColumnPosition) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + if (FindFirstFreeCol(_rColumnPosition) == NULL) + { + // es ist voll, also einen Packen Spalten anhaengen + AppendNewCol(DEFAULT_QUERY_COLS); + OSL_VERIFY(FindFirstFreeCol(_rColumnPosition).is()); + } +} +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::AddGroupBy( const OTableFieldDescRef& rInfo , sal_uInt32 /*_nCurrentPos*/) +{ + Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); + if(!xConnection.is()) + return; + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + DBG_ASSERT(!rInfo->IsEmpty(),"AddGroupBy:: OTableFieldDescRef sollte nicht Empty sein!"); + OTableFieldDescRef pEntry; + const Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + const ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers()); + //sal_Bool bAppend = sal_False; + + OTableFields& rFields = getFields(); + OTableFields::iterator aIter = rFields.begin(); + OTableFields::iterator aEnd = rFields.end(); + for(;aIter != aEnd;++aIter) + { + pEntry = *aIter; + OSL_ENSURE(pEntry.is(),"OTableFieldDescRef was null!"); + + const ::rtl::OUString aField = pEntry->GetField(); + const ::rtl::OUString aAlias = pEntry->GetAlias(); + + if (bCase(aField,rInfo->GetField()) && + bCase(aAlias,rInfo->GetAlias()) && + pEntry->GetFunctionType() == rInfo->GetFunctionType() && + pEntry->GetFunction() == rInfo->GetFunction()) + { + if ( pEntry->isNumericOrAggreateFunction() && rInfo->IsGroupBy() ) + { + pEntry->SetGroupBy(sal_False); + aIter = rFields.end(); + break; + } + else + { + if ( !pEntry->IsGroupBy() && !pEntry->HasCriteria() ) // here we have a where condition which is no having clause + { + pEntry->SetGroupBy(rInfo->IsGroupBy()); + if(!m_bGroupByUnRelated && pEntry->IsGroupBy()) + pEntry->SetVisible(sal_True); + break; + } + } + + } + } + + if (aIter == rFields.end()) + { + OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID, sal_False, sal_False ); + if ( (pTmp->isNumericOrAggreateFunction() && rInfo->IsGroupBy()) ) // das GroupBy wird bereits von rInfo "ubernommen + pTmp->SetGroupBy(sal_False); + } +} +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::DuplicateConditionLevel( const sal_uInt16 nLevel) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + const sal_uInt16 nNewLevel = nLevel +1; + OTableFields& rFields = getFields(); + OTableFields::iterator aIter = rFields.begin(); + OTableFields::iterator aEnd = rFields.end(); + for(;aIter != aEnd;++aIter) + { + OTableFieldDescRef pEntry = *aIter; + + ::rtl::OUString sValue = pEntry->GetCriteria(nLevel); + if ( sValue.getLength() ) + { + pEntry->SetCriteria( nNewLevel, sValue); + if ( nNewLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1) ) + { + RowInserted( GetRowCount()-1, 1, TRUE ); + m_bVisibleRow.push_back(sal_True); + ++m_nVisibleCount; + } + m_bVisibleRow[BROW_CRIT1_ROW + nNewLevel] = sal_True; + } + } +} +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::AddCondition( const OTableFieldDescRef& rInfo, const String& rValue, const sal_uInt16 nLevel,bool _bAddOrOnOneLine ) +{ + Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); + if(!xConnection.is()) + return; + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + DBG_ASSERT(rInfo.is() && !rInfo->IsEmpty(),"AddCondition:: OTableFieldDescRef sollte nicht Empty sein!"); + + OTableFieldDescRef pLastEntry; + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers()); + + OTableFields& rFields = getFields(); + OTableFields::iterator aIter = rFields.begin(); + OTableFields::iterator aEnd = rFields.end(); + for(;aIter != aEnd;++aIter) + { + OTableFieldDescRef pEntry = *aIter; + const ::rtl::OUString aField = pEntry->GetField(); + const ::rtl::OUString aAlias = pEntry->GetAlias(); + + if (bCase(aField,rInfo->GetField()) && + bCase(aAlias,rInfo->GetAlias()) && + pEntry->GetFunctionType() == rInfo->GetFunctionType() && + pEntry->GetFunction() == rInfo->GetFunction() && + pEntry->IsGroupBy() == rInfo->IsGroupBy() ) + { + if ( pEntry->isNumericOrAggreateFunction() && rInfo->IsGroupBy() ) + pEntry->SetGroupBy(sal_False); + else + { + if(!m_bGroupByUnRelated && pEntry->IsGroupBy()) + pEntry->SetVisible(sal_True); + } + if (!pEntry->GetCriteria(nLevel).getLength() ) + { + pEntry->SetCriteria( nLevel, rValue); + if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1)) + { + RowInserted( GetRowCount()-1, 1, TRUE ); + m_bVisibleRow.push_back(sal_True); + ++m_nVisibleCount; + } + m_bVisibleRow[BROW_CRIT1_ROW + nLevel] = sal_True; + break; + } + if ( _bAddOrOnOneLine ) + { + pLastEntry = pEntry; + } + } + } + if ( pLastEntry.is() ) + { + String sCriteria = rValue; + String sOldCriteria = pLastEntry->GetCriteria( nLevel ); + if ( sOldCriteria.Len() ) + { + sCriteria = String(RTL_CONSTASCII_USTRINGPARAM("( ")); + sCriteria += sOldCriteria; + sCriteria += String(RTL_CONSTASCII_USTRINGPARAM(" OR ")); + sCriteria += rValue; + sCriteria += String(RTL_CONSTASCII_USTRINGPARAM(" )")); + } + pLastEntry->SetCriteria( nLevel, sCriteria); + if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1)) + { + RowInserted( GetRowCount()-1, 1, TRUE ); + m_bVisibleRow.push_back(sal_True); + ++m_nVisibleCount; + } + m_bVisibleRow[BROW_CRIT1_ROW + nLevel] = sal_True; + } + + else if (aIter == getFields().end()) + { + OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID, sal_False, sal_False ); + if ( pTmp->isNumericOrAggreateFunction() && rInfo->IsGroupBy() ) // das GroupBy wird bereits von rInfo "ubernommen + pTmp->SetGroupBy(sal_False); + if ( pTmp.is() ) + { + pTmp->SetCriteria( nLevel, rValue); + if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1)) + { + RowInserted( GetRowCount()-1, 1, TRUE ); + m_bVisibleRow.push_back(sal_True); + ++m_nVisibleCount; + } + } + } +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::AddOrder( const OTableFieldDescRef& rInfo, const EOrderDir eDir, sal_uInt32 _nCurrentPos) +{ + Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); + if(!xConnection.is()) + return; + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + DBG_ASSERT(!rInfo->IsEmpty(),"AddOrder:: OTableFieldDescRef sollte nicht Empty sein!"); + OTableFieldDescRef pEntry; + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers()); + + sal_Bool bAppend = sal_False; + OTableFields& rFields = getFields(); + OTableFields::iterator aIter = rFields.begin(); + OTableFields::iterator aEnd = rFields.end(); + for(;aIter != aEnd;++aIter) + { + pEntry = *aIter; + ::rtl::OUString aField = pEntry->GetField(); + ::rtl::OUString aAlias = pEntry->GetAlias(); + + if (bCase(aField,rInfo->GetField()) && + bCase(aAlias,rInfo->GetAlias())) + { + sal_uInt32 nPos = aIter - rFields.begin(); + bAppend = _nCurrentPos > nPos; + if ( bAppend ) + aIter = rFields.end(); + else + { + if ( !m_bOrderByUnRelated ) + pEntry->SetVisible(sal_True); + pEntry->SetOrderDir( eDir ); + } + break; + } + } + + if (aIter == rFields.end()) + { + OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID, sal_False, sal_False ); + if(pTmp.is()) + { + if ( !m_bOrderByUnRelated && !bAppend ) + pTmp->SetVisible(sal_True); + pTmp->SetOrderDir( eDir ); + } + } +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::ArrangeControls(sal_uInt16& nX, sal_uInt16 nY) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + EditBrowseBox::ArrangeControls(nX, nY); +} + +//------------------------------------------------------------------------------ +sal_Bool OSelectionBrowseBox::Save() +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + sal_Bool bRet = sal_True; + if (IsModified()) + bRet = SaveModified(); + return bRet; +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::CellModified() +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + long nRow = GetRealRow(GetCurRow()); + switch (nRow) + { + case BROW_VIS_ROW: + { + OTableFieldDescRef pEntry = getEntry(GetColumnPos(GetCurColumnId()) - 1); + + sal_uInt16 nIdx = m_pOrderCell->GetSelectEntryPos(); + if(!m_bOrderByUnRelated && nIdx > 0 && + nIdx != sal_uInt16(-1) && + !pEntry->IsEmpty() && + pEntry->GetOrderDir() != ORDER_NONE) + { + m_pVisibleCell->GetBox().Check(); + pEntry->SetVisible(sal_True); + } + else + pEntry->SetVisible(m_pVisibleCell->GetBox().IsChecked()); + } + break; + } + static_cast<OQueryController&>(getDesignView()->getController()).setModified( sal_True ); +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::Fill() +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + DBG_ASSERT(ColCount() >= 1, "OSelectionBrowseBox::Fill : please call only after inserting the handle column !"); + + sal_uInt16 nColCount = ColCount() - 1; + if (nColCount < DEFAULT_QUERY_COLS) + AppendNewCol(DEFAULT_QUERY_COLS - nColCount); +} + +//------------------------------------------------------------------------------ +Size OSelectionBrowseBox::CalcOptimalSize( const Size& _rAvailable ) +{ + Size aReturn( _rAvailable.Width(), GetTitleHeight() ); + + aReturn.Height() += ( m_nVisibleCount ? m_nVisibleCount : 15 ) * GetDataRowHeight(); + aReturn.Height() += 40; // just some space + + return aReturn; +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::Command(const CommandEvent& rEvt) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + switch (rEvt.GetCommand()) + { + case COMMAND_CONTEXTMENU: + { + Point aMenuPos( rEvt.GetMousePosPixel() ); + + if (!rEvt.IsMouseEvent()) + { + if ( 1 == GetSelectColumnCount() ) + { + sal_uInt16 nSelId = GetColumnId( + sal::static_int_cast< USHORT >( + FirstSelectedColumn() ) ); + ::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, sal_False ) ); + + aMenuPos = aColRect.TopCenter(); + } + else + { + EditBrowseBox::Command(rEvt); + return; + } + } + + sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel( aMenuPos.X() )); + long nRow = GetRowAtYPosPixel( aMenuPos.Y() ); + + if (nRow < 0 && nColId > HANDLE_ID ) + { + if ( !IsColumnSelected( nColId ) ) + { + adjustSelectionMode( sal_True /* clicked onto a header */ , sal_False /* not onto the handle col */ ); + SelectColumnId( nColId ); + } + + if (!static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly()) + { + PopupMenu aContextMenu( ModuleRes( RID_QUERYCOLPOPUPMENU ) ); + switch (aContextMenu.Execute(this, aMenuPos)) + { + case SID_DELETE: + RemoveField(nColId); + break; + + case ID_BROWSER_COLWIDTH: + adjustBrowseBoxColumnWidth( this, nColId ); + break; + } + } + } + else if(nRow >= 0 && nColId <= HANDLE_ID) + { + if (!static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly()) + { + PopupMenu aContextMenu(ModuleRes(RID_QUERYFUNCTION_POPUPMENU)); + aContextMenu.CheckItem( ID_QUERY_FUNCTION, m_bVisibleRow[BROW_FUNCTION_ROW]); + aContextMenu.CheckItem( ID_QUERY_TABLENAME, m_bVisibleRow[BROW_TABLE_ROW]); + aContextMenu.CheckItem( ID_QUERY_ALIASNAME, m_bVisibleRow[BROW_COLUMNALIAS_ROW]); + aContextMenu.CheckItem( ID_QUERY_DISTINCT, static_cast<OQueryController&>(getDesignView()->getController()).isDistinct()); + + switch (aContextMenu.Execute(this, aMenuPos)) + { + case ID_QUERY_FUNCTION: + SetRowVisible(BROW_FUNCTION_ROW, !IsRowVisible(BROW_FUNCTION_ROW)); + static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_FUNCTIONS ); + break; + case ID_QUERY_TABLENAME: + SetRowVisible(BROW_TABLE_ROW, !IsRowVisible(BROW_TABLE_ROW)); + static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_TABLES ); + break; + case ID_QUERY_ALIASNAME: + SetRowVisible(BROW_COLUMNALIAS_ROW, !IsRowVisible(BROW_COLUMNALIAS_ROW)); + static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_ALIASES ); + break; + case ID_QUERY_DISTINCT: + static_cast<OQueryController&>(getDesignView()->getController()).setDistinct(!static_cast<OQueryController&>(getDesignView()->getController()).isDistinct()); + static_cast<OQueryController&>(getDesignView()->getController()).setModified( sal_True ); + static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_DISTINCT_VALUES ); + break; + } + + static_cast<OQueryController&>(getDesignView()->getController()).setModified( sal_True ); + } + } + else + { + EditBrowseBox::Command(rEvt); + return; + } + } + default: + EditBrowseBox::Command(rEvt); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OSelectionBrowseBox::IsRowVisible(sal_uInt16 _nWhich) const +{ + DBG_ASSERT(_nWhich<(m_bVisibleRow.size()), "OSelectionBrowseBox::IsRowVisible : invalid parameter !"); + return m_bVisibleRow[_nWhich]; +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::SetRowVisible(sal_uInt16 _nWhich, sal_Bool _bVis) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + DBG_ASSERT(_nWhich<m_bVisibleRow.size(), "OSelectionBrowseBox::SetRowVisible : invalid parameter !"); + + sal_Bool bWasEditing = IsEditing(); + if (bWasEditing) + DeactivateCell(); + + // do this before removing or inserting rows, as this triggers ActivateCell-calls, which rely on m_bVisibleRow + m_bVisibleRow[_nWhich] = !m_bVisibleRow[_nWhich]; + + long nId = GetBrowseRow(_nWhich); + if (_bVis) + { + RowInserted(nId,1); + ++m_nVisibleCount; + } + else + { + RowRemoved(nId,1); + --m_nVisibleCount; + } + + if (bWasEditing) + ActivateCell(); +} + +//------------------------------------------------------------------------------ +long OSelectionBrowseBox::GetBrowseRow(long nRowId) const +{ + USHORT nCount(0); + for(USHORT i = 0 ; i < nRowId ; ++i) + { + if ( m_bVisibleRow[i] ) + ++nCount; + } + return nCount; +} +//------------------------------------------------------------------------------ +long OSelectionBrowseBox::GetRealRow(long nRowId) const +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + long nErg=0,i; + const long nCount = m_bVisibleRow.size(); + for(i=0;i < nCount; ++i) + { + if(m_bVisibleRow[i]) + { + if(nErg++ == nRowId) + break; + } + } + DBG_ASSERT(nErg <= long(m_bVisibleRow.size()),"nErg kann nicht groesser als BROW_ROW_CNT sein!"); + return i; +} +static long nVisibleRowMask[] = + { + 0x0001, + 0x0002, + 0x0004, + 0x0008, + 0x0010, + 0x0020, + 0x0040, + 0x0080, + 0x0100, + 0x0200, + 0x0400, + 0x0800 + }; +//------------------------------------------------------------------------------ +sal_Int32 OSelectionBrowseBox::GetNoneVisibleRows() const +{ + sal_Int32 nErg(0); + // only the first 11 row are interesting + sal_Int32 nSize = SAL_N_ELEMENTS(nVisibleRowMask); + for(sal_Int32 i=0;i<nSize;i++) + { + if(!m_bVisibleRow[i]) + nErg |= nVisibleRowMask[i]; + } + return nErg; +} +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::SetNoneVisbleRow(long nRows) +{ + // only the first 11 row are interesting + sal_Int32 nSize = SAL_N_ELEMENTS(nVisibleRowMask); + for(sal_Int32 i=0;i< nSize;i++) + m_bVisibleRow[i] = !(nRows & nVisibleRowMask[i]); +} +//------------------------------------------------------------------------------ +String OSelectionBrowseBox::GetCellText(long nRow, sal_uInt16 nColId) const +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + + USHORT nPos = GetColumnPos(nColId); + + OTableFieldDescRef pEntry = getFields()[nPos-1]; + DBG_ASSERT(pEntry != NULL, "OSelectionBrowseBox::GetCellText : invalid column id, prepare for GPF ... "); + if ( pEntry->IsEmpty() ) + return String(); + + String aText; + switch (nRow) + { + case BROW_TABLE_ROW: + aText = pEntry->GetAlias(); + break; + case BROW_FIELD_ROW: + { + String aField = pEntry->GetField(); + if (aField.GetChar(0) == '*') // * durch alias.* ersetzen + { + aField = pEntry->GetAlias(); + if(aField.Len()) + aField += '.'; + aField += '*'; + } + aText = aField; + } break; + case BROW_ORDER_ROW: + if (pEntry->GetOrderDir() != ORDER_NONE) + aText = String(ModuleRes(STR_QUERY_SORTTEXT) ).GetToken(sal::static_int_cast< USHORT >(pEntry->GetOrderDir())); + break; + case BROW_VIS_ROW: + break; + case BROW_COLUMNALIAS_ROW: + aText = pEntry->GetFieldAlias(); + break; + case BROW_FUNCTION_ROW: + // we always show the group function at first + if ( pEntry->IsGroupBy() ) + aText = m_aFunctionStrings.GetToken(m_aFunctionStrings.GetTokenCount()-1); + else if ( pEntry->isNumericOrAggreateFunction() ) + aText = pEntry->GetFunction(); + break; + default: + aText = pEntry->GetCriteria(sal_uInt16(nRow - BROW_CRIT1_ROW)); + } + return aText; +} +//------------------------------------------------------------------------------ +sal_Bool OSelectionBrowseBox::GetFunctionName(sal_uInt32 _nFunctionTokenId,String& rFkt) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + sal_Bool bErg=sal_True; + String aText; + switch(_nFunctionTokenId) + { + case SQL_TOKEN_COUNT: + rFkt = (m_pFunctionCell->GetEntryCount() < 3) ? m_pFunctionCell->GetEntry(1) : m_pFunctionCell->GetEntry(2); + break; + case SQL_TOKEN_AVG: + rFkt = m_pFunctionCell->GetEntry(1); + break; + case SQL_TOKEN_MAX: + rFkt = m_pFunctionCell->GetEntry(3); + break; + case SQL_TOKEN_MIN: + rFkt = m_pFunctionCell->GetEntry(4); + break; + case SQL_TOKEN_SUM: + rFkt = m_pFunctionCell->GetEntry(5); + break; + case SQL_TOKEN_EVERY: + rFkt = m_pFunctionCell->GetEntry(6); + break; + case SQL_TOKEN_ANY: + rFkt = m_pFunctionCell->GetEntry(7); + break; + case SQL_TOKEN_SOME: + rFkt = m_pFunctionCell->GetEntry(8); + break; + case SQL_TOKEN_STDDEV_POP: + rFkt = m_pFunctionCell->GetEntry(9); + break; + case SQL_TOKEN_STDDEV_SAMP: + rFkt = m_pFunctionCell->GetEntry(10); + break; + case SQL_TOKEN_VAR_SAMP: + rFkt = m_pFunctionCell->GetEntry(11); + break; + case SQL_TOKEN_VAR_POP: + rFkt = m_pFunctionCell->GetEntry(12); + break; + case SQL_TOKEN_COLLECT: + rFkt = m_pFunctionCell->GetEntry(13); + break; + case SQL_TOKEN_FUSION: + rFkt = m_pFunctionCell->GetEntry(14); + break; + case SQL_TOKEN_INTERSECTION: + rFkt = m_pFunctionCell->GetEntry(15); + break; + default: + { + xub_StrLen nCount = m_aFunctionStrings.GetTokenCount(); + xub_StrLen i; + for ( i = 0; i < nCount-1; i++) // Gruppierung wird nicht mit gez"ahlt + { + if(rFkt.EqualsIgnoreCaseAscii(m_aFunctionStrings.GetToken(i))) + { + rFkt = m_aFunctionStrings.GetToken(i); + break; + } + } + if(i == nCount-1) + bErg = sal_False; + } + } + + return bErg; +} +//------------------------------------------------------------------------------ +String OSelectionBrowseBox::GetCellContents(sal_Int32 nCellIndex, USHORT nColId) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + if ( GetCurColumnId() == nColId && !m_bInUndoMode ) + SaveModified(); + + USHORT nPos = GetColumnPos(nColId); + OTableFieldDescRef pEntry = getFields()[nPos - 1]; + DBG_ASSERT(pEntry != NULL, "OSelectionBrowseBox::GetCellContents : invalid column id, prepare for GPF ... "); + + switch (nCellIndex) + { + case BROW_VIS_ROW : + return pEntry->IsVisible() ? g_strOne : g_strZero; + case BROW_ORDER_ROW: + { + sal_uInt16 nIdx = m_pOrderCell->GetSelectEntryPos(); + if (nIdx == sal_uInt16(-1)) + nIdx = 0; + return String(nIdx); + } + default: + return GetCellText(nCellIndex, nColId); + } +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::SetCellContents(sal_Int32 nRow, USHORT nColId, const String& strNewText) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + sal_Bool bWasEditing = IsEditing() && (GetCurColumnId() == nColId) && IsRowVisible(static_cast<USHORT>(nRow)) && (GetCurRow() == static_cast<USHORT>(GetBrowseRow(nRow))); + if (bWasEditing) + DeactivateCell(); + + USHORT nPos = GetColumnPos(nColId); + OTableFieldDescRef pEntry = getEntry(nPos - 1); + DBG_ASSERT(pEntry != NULL, "OSelectionBrowseBox::SetCellContents : invalid column id, prepare for GPF ... "); + + + switch (nRow) + { + case BROW_VIS_ROW: + pEntry->SetVisible(strNewText.Equals(g_strOne)); + break; + case BROW_FIELD_ROW: + pEntry->SetField(strNewText); + break; + case BROW_TABLE_ROW: + pEntry->SetAlias(strNewText); + break; + case BROW_ORDER_ROW: + { + sal_uInt16 nIdx = (sal_uInt16)strNewText.ToInt32(); + pEntry->SetOrderDir(EOrderDir(nIdx)); + } break; + case BROW_COLUMNALIAS_ROW: + pEntry->SetFieldAlias(strNewText); + break; + case BROW_FUNCTION_ROW: + { + String sOldFunctionName = pEntry->GetFunction(); + String sGroupFunctionName = m_aFunctionStrings.GetToken(m_aFunctionStrings.GetTokenCount()-1); + pEntry->SetFunction(strNewText); + // first reset this two member + sal_Int32 nFunctionType = pEntry->GetFunctionType(); + nFunctionType &= ~FKT_AGGREGATE; + pEntry->SetFunctionType(nFunctionType); + if ( pEntry->IsGroupBy() && !sGroupFunctionName.EqualsIgnoreCaseAscii(strNewText) ) + pEntry->SetGroupBy(sal_False); + + + if ( sGroupFunctionName.EqualsIgnoreCaseAscii(strNewText) ) + pEntry->SetGroupBy(sal_True); + else if ( strNewText.Len() ) + { + nFunctionType |= FKT_AGGREGATE; + pEntry->SetFunctionType(nFunctionType); + } + } break; + default: + pEntry->SetCriteria(sal_uInt16(nRow - BROW_CRIT1_ROW), strNewText); + } + + long nCellIndex = GetRealRow(nRow); + if(IsRowVisible(static_cast<USHORT>(nRow))) + RowModified(nCellIndex, nColId); + + // die entsprechende Feld-Beschreibung ist jetzt leer -> Visible auf sal_False (damit das konsistent mit normalen leeren Spalten ist) + if (pEntry->IsEmpty()) + pEntry->SetVisible(sal_False); + + if (bWasEditing) + ActivateCell(nCellIndex, nColId); + + static_cast<OQueryController&>(getDesignView()->getController()).setModified( sal_True ); +} +//------------------------------------------------------------------------------ +sal_uInt32 OSelectionBrowseBox::GetTotalCellWidth(long nRow, sal_uInt16 nColId) const +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + + long nRowId = GetRealRow(nRow); + if (nRowId == BROW_VIS_ROW) + return CHECKBOX_SIZE; + else + return GetDataWindow().GetTextWidth(GetCellText(nRowId, nColId)); +} + +//------------------------------------------------------------------------------ +void OSelectionBrowseBox::ColumnResized(sal_uInt16 nColId) +{ + if (static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly()) + return; + // The resizing of columns can't be suppressed (BrowseBox doesn't support that) so we have to do this + // fake. It's not _that_ bad : the user may change column widths while in read-only mode to see all details + // but the changes aren't permanent ... + + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + USHORT nPos = GetColumnPos(nColId); + DBG_ASSERT(nPos <= getFields().size(),"ColumnResized:: nColId sollte nicht groesser als List::count sein!"); + OTableFieldDescRef pEntry = getEntry(nPos-1); + DBG_ASSERT(pEntry.is(), "OSelectionBrowseBox::ColumnResized : keine FieldDescription !"); + static_cast<OQueryController&>(getDesignView()->getController()).setModified( sal_True ); + EditBrowseBox::ColumnResized(nColId); + + if ( pEntry.is()) + { + if ( !m_bInUndoMode ) + { + // create the undo action + OTabFieldSizedUndoAct* pUndo = new OTabFieldSizedUndoAct(this); + pUndo->SetColumnPosition( nPos ); + pUndo->SetOriginalWidth(pEntry->GetColWidth()); + getDesignView()->getController().addUndoActionAndInvalidate(pUndo); + } + pEntry->SetColWidth(sal_uInt16(GetColumnWidth(nColId))); + } +} + +//------------------------------------------------------------------------------ +sal_uInt32 OSelectionBrowseBox::GetTotalCellWidth(long nRowId, sal_uInt16 nColId) +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + USHORT nPos = GetColumnPos(nColId); + DBG_ASSERT((nPos == 0) || (nPos <= getFields().size()), "OSelectionBrowseBox::GetTotalCellWidth : invalid parameter nColId"); + + OTableFieldDescRef pEntry = getFields()[nPos-1]; + DBG_ASSERT(pEntry.is(), "OSelectionBrowseBox::GetTotalCellWidth : invalid FieldDescription !"); + + long nRow = GetRealRow(nRowId); + String strText(GetCellText(nRow, nColId)); + return GetDataWindow().LogicToPixel(Size(GetDataWindow().GetTextWidth(strText),0)).Width(); +} + +//------------------------------------------------------------------------------ +sal_uInt16 OSelectionBrowseBox::GetDefaultColumnWidth(const String& /*rName*/) const +{ + DBG_CHKTHIS(OSelectionBrowseBox,NULL); + // die Baissklasse macht das von dem Text abhaengig, ich habe aber keine Spaltenueberschriften, daher haette ich + // hier gern einen anderen Default-Wert + return static_cast<sal_uInt16>(DEFAULT_SIZE); +} +//------------------------------------------------------------------------------ +sal_Bool OSelectionBrowseBox::isCutAllowed() +{ + sal_Bool bCutAllowed = sal_False; + long nRow = GetRealRow(GetCurRow()); + switch (nRow) + { + case BROW_VIS_ROW: + case BROW_ORDER_ROW: + case BROW_TABLE_ROW: + case BROW_FUNCTION_ROW: + break; + case BROW_FIELD_ROW: + bCutAllowed = m_pFieldCell->GetSelected().Len() != 0; + break; + default: + bCutAllowed = m_pTextCell->GetSelected().Len() != 0; + break; + } + return bCutAllowed; +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::cut() +{ + String sOldValue = GetCellContents(GetRealRow(GetCurRow()),GetCurColumnId()); + long nRow = GetRealRow(GetCurRow()); + switch (nRow) + { + case BROW_FIELD_ROW: + m_pFieldCell->Cut(); + m_pFieldCell->SetModifyFlag(); + break; + default: + m_pTextCell->Cut(); + m_pTextCell->SetModifyFlag(); + } + SaveModified(); + RowModified(GetBrowseRow(nRow), GetCurColumnId()); + + invalidateUndoRedo(); +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::paste() +{ + long nRow = GetRealRow(GetCurRow()); + switch (nRow) + { + case BROW_FIELD_ROW: + m_pFieldCell->Paste(); + m_pFieldCell->SetModifyFlag(); + break; + default: + m_pTextCell->Paste(); + m_pTextCell->SetModifyFlag(); + } + RowModified(GetBrowseRow(nRow), GetCurColumnId()); + invalidateUndoRedo(); +} +// ----------------------------------------------------------------------------- +sal_Bool OSelectionBrowseBox::isPasteAllowed() +{ + sal_Bool bPasteAllowed = sal_True; + long nRow = GetRealRow(GetCurRow()); + switch (nRow) + { + case BROW_VIS_ROW: + case BROW_ORDER_ROW: + case BROW_TABLE_ROW: + case BROW_FUNCTION_ROW: + bPasteAllowed = sal_False; + break; + } + return bPasteAllowed; +} +// ----------------------------------------------------------------------------- +sal_Bool OSelectionBrowseBox::isCopyAllowed() +{ + return isCutAllowed(); +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::copy() +{ + long nRow = GetRealRow(GetCurRow()); + switch (nRow) + { + case BROW_FIELD_ROW: + m_pFieldCell->Copy(); + break; + default: + m_pTextCell->Copy(); + } +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::appendUndoAction(const String& _rOldValue,const String& _rNewValue,sal_Int32 _nRow,sal_Bool& _bListAction) +{ + if ( !m_bInUndoMode && !_rNewValue.Equals(_rOldValue) ) + { + if ( !_bListAction ) + { + _bListAction = sal_True; + static_cast<OQueryController&>(getDesignView()->getController()).getUndoMgr()->EnterListAction(String(),String()); + } + appendUndoAction(_rOldValue,_rNewValue,_nRow); + } +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::appendUndoAction(const String& _rOldValue,const String& _rNewValue,sal_Int32 _nRow) +{ + if ( !m_bInUndoMode && !_rNewValue.Equals(_rOldValue) ) + { + OTabFieldCellModifiedUndoAct* pUndoAct = new OTabFieldCellModifiedUndoAct(this); + pUndoAct->SetCellIndex(_nRow); + OSL_ENSURE(GetColumnPos(GetCurColumnId()) != BROWSER_INVALIDID,"Current position isn't valid!"); + pUndoAct->SetColumnPosition( GetColumnPos(GetCurColumnId()) ); + pUndoAct->SetCellContents(_rOldValue); + getDesignView()->getController().addUndoActionAndInvalidate(pUndoAct); + } +} +// ----------------------------------------------------------------------------- +IMPL_LINK(OSelectionBrowseBox, OnInvalidateTimer, void*, EMPTYARG) +{ + static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_CUT); + static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_COPY); + static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_PASTE); + if(!m_bStopTimer) + m_timerInvalidate.Start(); + return 0L; +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::stopTimer() +{ + m_bStopTimer = sal_True; + if (m_timerInvalidate.IsActive()) + m_timerInvalidate.Stop(); +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::startTimer() +{ + m_bStopTimer = sal_False; + if (!m_timerInvalidate.IsActive()) + m_timerInvalidate.Start(); +} +// ----------------------------------------------------------------------------- +OTableFields& OSelectionBrowseBox::getFields() const +{ + OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController()); + return rController.getTableFieldDesc(); +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::enableControl(const OTableFieldDescRef& _rEntry,Window* _pControl) +{ + BOOL bEnable = !_rEntry->isCondition(); + _pControl->Enable(bEnable); + _pControl->EnableInput(bEnable); +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::setTextCellContext(const OTableFieldDescRef& _rEntry,const String& _sText,ULONG _nHelpId) +{ + m_pTextCell->SetText(_sText); + m_pTextCell->ClearModifyFlag(); + if (!m_pTextCell->HasFocus()) + m_pTextCell->GrabFocus(); + + enableControl(_rEntry,m_pTextCell); + + if (m_pTextCell->GetHelpId() != _nHelpId) + // da TextCell in verschiedenen Kontexten verwendet wird, muss ich den gecachten HelpText loeschen + m_pTextCell->SetHelpText(String()); + m_pTextCell->SetHelpId(_nHelpId); +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::invalidateUndoRedo() +{ + OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController()); + rController.InvalidateFeature( ID_BROWSER_UNDO ); + rController.InvalidateFeature( ID_BROWSER_REDO ); + rController.InvalidateFeature( ID_BROWSER_QUERY_EXECUTE ); +} +// ----------------------------------------------------------------------------- +OTableFieldDescRef OSelectionBrowseBox::getEntry(OTableFields::size_type _nPos) +{ + // we have to check if we need a new entry at this position + OTableFields& aFields = getFields(); + OSL_ENSURE(aFields.size() > _nPos,"ColID is to great!"); + + OTableFieldDescRef pEntry = aFields[_nPos]; + OSL_ENSURE(pEntry.is(),"Invalid entry!"); + if ( !pEntry.is() ) + { + pEntry = new OTableFieldDesc(); + pEntry->SetColumnId( + GetColumnId(sal::static_int_cast< USHORT >(_nPos+1))); + aFields[_nPos] = pEntry; + } + return pEntry; +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::GetFocus() +{ + if(!IsEditing() && !m_bWasEditing) + ActivateCell(); + EditBrowseBox::GetFocus(); +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::DeactivateCell(sal_Bool _bUpdate) +{ + m_bWasEditing = sal_True; + EditBrowseBox::DeactivateCell(_bUpdate); + m_bWasEditing = sal_False; +} +// ----------------------------------------------------------------------------- +::rtl::OUString OSelectionBrowseBox::GetRowDescription( sal_Int32 _nRow ) const +{ + String aLabel(ModuleRes(STR_QUERY_HANDLETEXT)); + + // ab BROW_CRIT2_ROW werden alle Zeilen mit "oder" angegeben + xub_StrLen nToken = (xub_StrLen) (_nRow >= GetBrowseRow(BROW_CRIT2_ROW)) + ? + xub_StrLen(BROW_CRIT2_ROW) : xub_StrLen(GetRealRow(_nRow)); + return ::rtl::OUString(aLabel.GetToken(nToken)); +} +// ----------------------------------------------------------------------------- +::rtl::OUString OSelectionBrowseBox::GetAccessibleObjectName( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition) const +{ + ::rtl::OUString sRetText; + switch( _eObjType ) + { + case ::svt::BBTYPE_ROWHEADERCELL: + sRetText = GetRowDescription(_nPosition); + break; + default: + sRetText = EditBrowseBox::GetAccessibleObjectDescription(_eObjType,_nPosition); + } + return sRetText; +} +// ----------------------------------------------------------------------------- +sal_Bool OSelectionBrowseBox::fillEntryTable(OTableFieldDescRef& _pEntry,const ::rtl::OUString& _sTableName) +{ + sal_Bool bRet = sal_False; + OJoinTableView::OTableWindowMap* pTabWinList = getDesignView()->getTableView()->GetTabWinMap(); + if (pTabWinList) + { + OJoinTableView::OTableWindowMapIterator aIter = pTabWinList->find(_sTableName); + if(aIter != pTabWinList->end()) + { + OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(aIter->second); + if (pEntryTab) + { + _pEntry->SetTable(pEntryTab->GetTableName()); + _pEntry->SetTabWindow(pEntryTab); + bRet = sal_True; + } + } + } + return bRet; +} +// ----------------------------------------------------------------------------- +void OSelectionBrowseBox::setFunctionCell(OTableFieldDescRef& _pEntry) +{ + Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); + if ( xConnection.is() ) + { + // Diese Funktionen stehen nur unter CORE zur Verfügung + if ( lcl_SupportsCoreSQLGrammar(xConnection) ) + { + // if we have an asterix, no other function than count is allowed + m_pFunctionCell->Clear(); + m_pFunctionCell->InsertEntry(m_aFunctionStrings.GetToken(0)); + if ( isFieldNameAsterix(_pEntry->GetField()) ) + m_pFunctionCell->InsertEntry(m_aFunctionStrings.GetToken(2)); // 2 -> COUNT + else + { + xub_StrLen nCount = m_aFunctionStrings.GetTokenCount(); + if ( _pEntry->isNumeric() ) + --nCount; + for (xub_StrLen nIdx = 1; nIdx < nCount; nIdx++) + m_pFunctionCell->InsertEntry(m_aFunctionStrings.GetToken(nIdx)); + } + + if ( _pEntry->IsGroupBy() ) + { + OSL_ENSURE(!_pEntry->isNumeric(),"Not allowed to combine group by and numeric values!"); + m_pFunctionCell->SelectEntry(m_pFunctionCell->GetEntry(m_pFunctionCell->GetEntryCount() - 1)); + } + else if ( m_pFunctionCell->GetEntryPos(String(_pEntry->GetFunction())) != COMBOBOX_ENTRY_NOTFOUND ) + m_pFunctionCell->SelectEntry(String(_pEntry->GetFunction())); + else + m_pFunctionCell->SelectEntryPos(0); + + enableControl(_pEntry,m_pFunctionCell); + } + else + { + // nur COUNT(*) erlaubt + sal_Bool bCountRemoved = !isFieldNameAsterix(_pEntry->GetField()); + if ( bCountRemoved ) + m_pFunctionCell->RemoveEntry(1); + + if ( !bCountRemoved && m_pFunctionCell->GetEntryCount() < 2) + m_pFunctionCell->InsertEntry(m_aFunctionStrings.GetToken(2)); // 2 -> COUNT + + if(m_pFunctionCell->GetEntryPos(String(_pEntry->GetFunction())) != COMBOBOX_ENTRY_NOTFOUND) + m_pFunctionCell->SelectEntry(_pEntry->GetFunction()); + else + m_pFunctionCell->SelectEntryPos(0); + } + } +} +// ----------------------------------------------------------------------------- +Reference< XAccessible > OSelectionBrowseBox::CreateAccessibleCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos ) +{ + OTableFieldDescRef pEntry = NULL; + if(getFields().size() > sal_uInt16(_nColumnPos - 1)) + pEntry = getFields()[_nColumnPos - 1]; + + if ( _nRow == BROW_VIS_ROW && pEntry.is() ) + return EditBrowseBox::CreateAccessibleCheckBoxCell( _nRow, _nColumnPos,pEntry->IsVisible() ? STATE_CHECK : STATE_NOCHECK ); + + return EditBrowseBox::CreateAccessibleCell( _nRow, _nColumnPos ); +} +// ----------------------------------------------------------------------------- +bool OSelectionBrowseBox::HasFieldByAliasName(const ::rtl::OUString& rFieldName, OTableFieldDescRef& rInfo) const +{ + OTableFields& aFields = getFields(); + OTableFields::iterator aIter = aFields.begin(); + OTableFields::iterator aEnd = aFields.end(); + + for(;aIter != aEnd;++aIter) + { + if ( (*aIter)->GetFieldAlias() == rFieldName ) + { + *rInfo = *(*aIter); + break; + } + } + return aIter != aEnd; +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/SelectionBrowseBox.hxx b/dbaccess/source/ui/querydesign/SelectionBrowseBox.hxx new file mode 100644 index 000000000000..8d25da432916 --- /dev/null +++ b/dbaccess/source/ui/querydesign/SelectionBrowseBox.hxx @@ -0,0 +1,347 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QUERYDESIGN_OSELECTIONBROWSEBOX_HXX +#define DBAUI_QUERYDESIGN_OSELECTIONBROWSEBOX_HXX + +#include <svtools/editbrowsebox.hxx> +#include "TableFieldDescription.hxx" +#include "JoinExchange.hxx" +#include "QEnumTypes.hxx" +#include <com/sun/star/util/XNumberFormatter.hpp> +#include <tools/string.hxx> +#include <svtools/transfer.hxx> + +namespace connectivity +{ + class OSQLParseNode; +} + +namespace dbaui +{ + //================================================================== +#define SIZ_NONE 0 +#define SIZ_TOP 1 +#define SIZ_BOTTOM 2 +#define SIZ_LEFT 4 +#define SIZ_RIGHT 8 + +#define BROW_FIELD_ROW 0 +#define BROW_COLUMNALIAS_ROW 1 +#define BROW_TABLE_ROW 2 +#define BROW_ORDER_ROW 3 +#define BROW_VIS_ROW 4 +#define BROW_FUNCTION_ROW 5 +#define BROW_CRIT1_ROW 6 +#define BROW_CRIT2_ROW 7 +#define BROW_CRIT3_ROW 8 +#define BROW_CRIT4_ROW 9 +#define BROW_CRIT5_ROW 10 +#define BROW_CRIT6_ROW 11 +#define BROW_ROW_CNT 12 + + //================================================================== + class OQueryDesignView; + class OSelectionBrowseBox : public ::svt::EditBrowseBox + { + friend class OQueryDesignView; + ::std::vector<bool> m_bVisibleRow; // an Pos steht die RowId + Timer m_timerInvalidate; + + long m_nSeekRow; + BrowserMode m_nMode; // Merken des BrowseModes + Edit* m_pTextCell; + ::svt::CheckBoxControl* m_pVisibleCell; + ::svt::ComboBoxControl* m_pFieldCell; + ::svt::ListBoxControl* m_pFunctionCell; + ::svt::ListBoxControl* m_pTableCell; + ::svt::ListBoxControl* m_pOrderCell; + + OTableFieldDescRef m_pEmptyEntry; // default entry in the list may reference more than once + + sal_Int32 m_nMaxColumns; // maximale Anzahl der Spalten in einem Select-Statement + + String m_aFunctionStrings; + sal_uInt16 m_nVisibleCount; // Anzahl der max sichtbaren Zeilen + sal_Bool m_bOrderByUnRelated; + sal_Bool m_bGroupByUnRelated; + sal_Bool m_bStopTimer; + sal_Bool m_bWasEditing; + sal_Bool m_bDisableErrorBox; + sal_Bool m_bInUndoMode; + + DECL_LINK(OnInvalidateTimer, void*); + public: OSelectionBrowseBox( Window* pParent ); + ~OSelectionBrowseBox(); + + void initialize(); + OTableFieldDescRef InsertField( const OJoinExchangeData& jxdSource, USHORT _nColumnPostion = BROWSER_INVALIDID, sal_Bool bVis=sal_True, sal_Bool bActivate=sal_True ); + OTableFieldDescRef InsertField( const OTableFieldDescRef& rInfo, USHORT _nColumnPostion = BROWSER_INVALIDID, sal_Bool bVis=sal_True, sal_Bool bActivate=sal_True ); + void InsertColumn( OTableFieldDescRef pEntry, USHORT& _nColumnPostion ); + void RemoveColumn( USHORT _nColumnId ); + void DeleteFields( const String& rAliasName ); + + bool HasFieldByAliasName(const ::rtl::OUString& rFieldName, OTableFieldDescRef& rInfo) const; + // AddGroupBy:: F"ugt ein Feld mit Funktion == Grupierung. Falls das Feld schon vorhanden ist und ein Aggregate Funktion + // benutzt, wird das Flag nicht gesetzt + void AddGroupBy( const OTableFieldDescRef& rInfo,sal_uInt32 _nCurrentPos); + void AddCondition( const OTableFieldDescRef& rInfo, + const String& rValue, + const sal_uInt16 nLevel, + bool _bAddOrOnOneLine ); + void DuplicateConditionLevel( const sal_uInt16 nLevel); + void AddOrder(const OTableFieldDescRef& rInfo, const EOrderDir eDir, sal_uInt32 _nCurrentPos); + void ClearAll(); + OTableFieldDescRef AppendNewCol( sal_uInt16 nCnt=1 ); + sal_Bool Save(); + OQueryDesignView* getDesignView(); + OQueryDesignView* getDesignView() const; + sal_uInt16 FieldsCount(); + + void SetColWidth(sal_uInt16 nColId, long lNewWidth); + // beachtet im Gegensatz zum SetColumnWidth der Basisklasse auch eine eventuell aktive Zelle in dieser Spalte + + String GetCellContents(sal_Int32 nCellIndex, USHORT nColId); + void SetCellContents(sal_Int32 nCellIndex, USHORT nColId, const String& strNewText); + // Zelleninhalt (als String formatiert) setzen/liefern + sal_Int32 GetNoneVisibleRows() const; + void SetNoneVisbleRow(long nRows); + sal_Bool IsRowVisible(sal_uInt16 _nWhich) const; + void SetRowVisible(sal_uInt16 _nWhich, sal_Bool _bVis); + + void SetReadOnly(sal_Bool bRO); + // calculate an optimal size. Basically, this takes into account the number of visible rows. + Size CalcOptimalSize( const Size& _rAvailable ); + + // can the current content be cut + sal_Bool isPasteAllowed(); + sal_Bool isCutAllowed(); + sal_Bool isCopyAllowed(); + void cut(); + void paste(); + void copy(); + + virtual void GetFocus(); + virtual void DeactivateCell(sal_Bool bUpdate = sal_True); + virtual void ColumnMoved( USHORT nColId ) { ColumnMoved(nColId,TRUE); } + void ColumnMoved( USHORT nColId,BOOL _bCreateUndo); + + void Fill(); + void PreFill(); + + /** Disables the generation of undo actions + */ + inline void EnterUndoMode() { m_bInUndoMode = sal_True; } + /** Enables the generation of undo actions + */ + inline void LeaveUndoMode() { m_bInUndoMode = sal_False; } + + /** GetCellText returns the text at the given position + @param _nRow + the number of the row + @param _nColId + the ID of the column + @return + the text out of the cell + */ + virtual String GetCellText(long _nRow, USHORT _nColId) const; + + /** returns the description of the row. + @param _nRow + The row number. + @return + The header text of the specified row. + */ + virtual ::rtl::OUString GetRowDescription( sal_Int32 _nRow ) const; + + /** return the name of the specified object. + @param eObjType + The type to ask for + @param _nPosition + The position of a tablecell (index position), header bar colum/row cell + @return + The name of the specified object. + */ + virtual ::rtl::OUString GetAccessibleObjectName( ::svt::AccessibleBrowseBoxObjType eObjType,sal_Int32 _nPosition = -1) const; + + // IAccessibleTableProvider + /** Creates the accessible object of a data table cell. + @param nRow The row index of the cell. + @param nColumnId The column ID of the cell. + @return The XAccessible interface of the specified cell. */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessibleCell( sal_Int32 nRow, sal_uInt16 nColumnId ); + + + protected: + virtual sal_Bool SeekRow( long nRow ); + + virtual void PaintStatusCell(OutputDevice& rDev, const Rectangle& rRect) const; + virtual void PaintCell(OutputDevice& rDev, const Rectangle& rRect, + sal_uInt16 nColumnId ) const; + + virtual sal_Int8 AcceptDrop( const BrowserAcceptDropEvent& rEvt ); + virtual sal_Int8 ExecuteDrop( const BrowserExecuteDropEvent& rEvt ); + virtual void MouseButtonDown( const BrowserMouseEvent& rEvt ); + virtual void MouseButtonUp( const BrowserMouseEvent& rEvt ); + virtual void KeyInput( const KeyEvent& rEvt ); + virtual void Command(const CommandEvent& rEvt); + virtual void ArrangeControls(sal_uInt16& nX, sal_uInt16 nY); + + virtual ::svt::CellController* GetController(long nRow, sal_uInt16 nCol); + virtual void InitController(::svt::CellControllerRef& rController, long nRow, sal_uInt16 nCol); + virtual void CellModified(); + virtual sal_Bool SaveModified(); + virtual void Init(); + virtual sal_uInt32 GetTotalCellWidth(long nRow, sal_uInt16 nColId) const; + virtual void ColumnResized( sal_uInt16 nColId ); + + virtual sal_uInt32 GetTotalCellWidth(long nRow, sal_uInt16 nColId); + + virtual sal_uInt16 GetDefaultColumnWidth(const String& rName) const; + // if you want to have an own header ... + virtual BrowserHeader* imp_CreateHeaderBar(BrowseBox* pParent); + + void stopTimer(); + void startTimer(); + + private: + OTableFieldDescRef FindFirstFreeCol(USHORT& _rColumnPosition); + // rCol enthaelt die Nummer (in pOTableFieldDescList) der ersten Spalte, die von sich sagt, dass sie leer ist + // wenn es keine solche gibt, ist rCol undefiniert und der Rueckgabewert NULL + void CheckFreeColumns(USHORT& _rColumnPosition); + // testet, ob es noch freie Spalten gibt, wenn nicht, wird ein neuer Packen angefuegt + // rCol enthaelt die Nummer der ersten freien Spalte (in pOTableFieldDescList) + + void RemoveField( sal_uInt16 nId ); + Rectangle GetInvalidRect( sal_uInt16 nColId ); + long GetRealRow(long nRow) const; + long GetBrowseRow(long nRowId) const; + sal_Bool GetFunctionName(sal_uInt32 _nFunctionTokenId,String& rFkt); + void appendUndoAction(const String& _rOldValue,const String& _rNewValue,sal_Int32 _nRow,sal_Bool& _bListAction); + void appendUndoAction(const String& _rOldValue,const String& _rNewValue,sal_Int32 _nRow); + OTableFields& getFields() const; + void enableControl(const OTableFieldDescRef& _rEntry,Window* _pControl); + void setTextCellContext(const OTableFieldDescRef& _rEntry,const String& _sText,ULONG _nHelpId); + void invalidateUndoRedo(); + OTableFieldDescRef getEntry(OTableFields::size_type _nPos); + + void adjustSelectionMode( sal_Bool _bClickedOntoHeader, sal_Bool _bClickedOntoHandleCol ); + + /** save the filed change in save modified + @param _sFieldName + The field name inserted by the user. + @param _pEntry + The entry which will contain the nescessary entries. + @param _bListAction + Will be set to <TRUE/> when we are in a list action otherwise <FALSE/> + @return + <TRUE/> if an error occurred otherwise <FALSE/> + */ + sal_Bool saveField(const String& _sFieldName,OTableFieldDescRef& _pEntry,sal_Bool& _bListAction); + + /** sets the table window at the _pEntry + @param _pEntry + The entry where the window should be set. + @param _sTableName + The table name to search for. + @return + <TRUE/> if the table name was set otherwise <FALSE/> + */ + sal_Bool fillEntryTable(OTableFieldDescRef& _pEntry,const ::rtl::OUString& _sTableName); + + /** uses the parse node to fill all information into the field + @param _pColumnRef + The parse node used to fill the info into the field. + @param _xMetaData + Use to parse the node to a string. + @param _pEntry + The entry which will contain the nescessary entries. + @param _bListAction + Will be set to <TRUE/> when we are in a list action otherwise <FALSE/> + @return + <TRUE/> if an error occurred otherwise <FALSE/> + */ + sal_Bool fillColumnRef( const ::connectivity::OSQLParseNode* _pColumnRef, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection, + OTableFieldDescRef& _pEntry, + sal_Bool& _bListAction); + sal_Bool fillColumnRef( const ::rtl::OUString& _sColumnName, + const ::rtl::OUString& _sTableRange, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _xMetaData, + OTableFieldDescRef& _pEntry, + sal_Bool& _bListAction); + + + /** append an undo action for the table field + @param _sOldAlias + The old table alias. + @param _sAlias + The new alias name. + @param _bListAction + Will be set to <TRUE/> when we are in a list action otherwise <FALSE/> + */ + void notifyTableFieldChanged(const String& _sOldAlias,const String& _sAlias,sal_Bool& _bListAction,USHORT _nColumnId); + + /** append an undo action for the function field + @param _sOldFunctionName + The old value. + @param _sFunctionName + The new function name. + @param _bListAction + Will be set to <TRUE/> when we are in a list action otherwise <FALSE/> + */ + void notifyFunctionFieldChanged(const String& _sOldFunctionName,const String& _sFunctionName,sal_Bool& _bListAction,USHORT _nColumnId); + + /** clears the function fields of the submitted entry if it doesn't match the SQL standard and append an undo action. + E.q. AGGREGATE functions are only valid when the field name isn't an asterix + @param _sFieldName + The field name. + @param _pEntry + The entry to be cleared + @param _bListAction + When <TRUE/> an list action will be created. + */ + void clearEntryFunctionField(const String& _sFieldName,OTableFieldDescRef& _pEntry,sal_Bool& _bListAction,USHORT _nColumnId); + + /** remove or insert the necessary function types + @param _pEntry + The currently edited entry. + */ + void setFunctionCell(OTableFieldDescRef& _pEntry); + + private: + using ::svt::EditBrowseBox::AcceptDrop; + using ::svt::EditBrowseBox::ExecuteDrop; + using ::svt::EditBrowseBox::MouseButtonDown; + using ::svt::EditBrowseBox::MouseButtonUp; + }; +} +#endif // DBAUI_QUERYDESIGN_OSELECTIONBROWSEBOX_HXX + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/TableConnection.cxx b/dbaccess/source/ui/querydesign/TableConnection.cxx new file mode 100644 index 000000000000..964b54d00f25 --- /dev/null +++ b/dbaccess/source/ui/querydesign/TableConnection.cxx @@ -0,0 +1,246 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "TableConnection.hxx" +#include "ConnectionLine.hxx" +#include "TableConnectionData.hxx" +#include "JoinTableView.hxx" +#include <comphelper/stl_types.hxx> +#include "ConnectionLineAccess.hxx" +#include <algorithm> + + +using namespace dbaui; +using namespace comphelper; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::accessibility; + +//======================================================================== +// class OTableConnection +//======================================================================== +namespace dbaui +{ + DBG_NAME(OTableConnection) + //------------------------------------------------------------------------ + OTableConnection::OTableConnection( OJoinTableView* _pContainer,const TTableConnectionData::value_type& _pTabConnData ) + :Window(_pContainer) + ,m_pData( _pTabConnData ) + ,m_pParent( _pContainer ) + ,m_bSelected( FALSE ) + { + DBG_CTOR(OTableConnection,NULL); + Init(); + Show(); + } + + //------------------------------------------------------------------------ + OTableConnection::OTableConnection( const OTableConnection& _rConn ) : Window(_rConn.m_pParent) + ,m_pData(_rConn.GetData()->NewInstance()) + { + DBG_CTOR(OTableConnection,NULL); + *this = _rConn; + } + + //------------------------------------------------------------------------ + void OTableConnection::Init() + { + ////////////////////////////////////////////////////////////////////// + // Linienliste mit Defaults initialisieren + OConnectionLineDataVec* pLineData = GetData()->GetConnLineDataList(); + OConnectionLineDataVec::const_iterator aIter = pLineData->begin(); + OConnectionLineDataVec::const_iterator aEnd = pLineData->end(); + m_vConnLine.reserve(pLineData->size()); + for(;aIter != aEnd;++aIter) + m_vConnLine.push_back( new OConnectionLine(this, *aIter) ); + } + + //------------------------------------------------------------------------ + OConnectionLine* OTableConnection::CreateConnLine( const OConnectionLine& rConnLine ) + { + return new OConnectionLine( rConnLine ); + } + // ----------------------------------------------------------------------------- + void OTableConnection::clearLineData() + { + ::std::vector<OConnectionLine*>::iterator aLineEnd = m_vConnLine.end(); + for(::std::vector<OConnectionLine*>::iterator aLineIter = m_vConnLine.begin();aLineIter != aLineEnd;++aLineIter) + delete *aLineIter; + m_vConnLine.clear(); + } + //------------------------------------------------------------------------ + void OTableConnection::UpdateLineList() + { + ////////////////////////////////////////////////////////////////////// + // Linienliste loeschen + clearLineData(); + + Init(); + } + + //------------------------------------------------------------------------ + OTableConnection& OTableConnection::operator=( const OTableConnection& rConn ) + { + if( &rConn == this ) + return *this; + + // Linienliste loeschen + clearLineData(); + + // Linienliste kopieren + if(! rConn.GetConnLineList()->empty() ) + { + const ::std::vector<OConnectionLine*>* pLine = rConn.GetConnLineList(); + ::std::vector<OConnectionLine*>::const_iterator aIter = pLine->begin(); + ::std::vector<OConnectionLine*>::const_iterator aEnd = pLine->end(); + m_vConnLine.reserve(pLine->size()); + for(;aIter != aEnd;++aIter) + m_vConnLine.push_back( CreateConnLine( **aIter )); + } + + // da mir die Daten nicht gehoeren, loesche ich die alten nicht + m_pData->CopyFrom(*rConn.GetData()); + // CopyFrom ist virtuell, damit ist es kein Problem, wenn m_pData von einem von OTableConnectionData abgeleiteten Typ ist + + m_bSelected = rConn.m_bSelected; + m_pParent = rConn.m_pParent; + + return *this; + } + + + //------------------------------------------------------------------------ + bool OTableConnection::RecalcLines() + { + // call RecalcLines on each line + ::std::for_each(m_vConnLine.begin(),m_vConnLine.end(),::std::mem_fun(&OConnectionLine::RecalcLine)); + return true; + } + //------------------------------------------------------------------------ + OTableWindow* OTableConnection::GetSourceWin() const + { + TTableWindowData::value_type pRef = GetData()->getReferencingTable(); + OTableWindow* pRet = m_pParent->GetTabWindow( pRef->GetWinName() ); + if ( !pRet ) + { + pRet = m_pParent->GetTabWindow( pRef->GetComposedName() ); + } + return pRet; + } + //------------------------------------------------------------------------ + OTableWindow* OTableConnection::GetDestWin() const + { + TTableWindowData::value_type pRef = GetData()->getReferencedTable(); + OTableWindow* pRet = m_pParent->GetTabWindow( pRef->GetWinName() ); + if ( !pRet ) + { + pRet = m_pParent->GetTabWindow( pRef->GetComposedName() ); + } + return pRet; + } + + //------------------------------------------------------------------------ + void OTableConnection::Select() + { + m_bSelected = TRUE; + m_pParent->Invalidate( GetBoundingRect(), INVALIDATE_NOCHILDREN); + } + + //------------------------------------------------------------------------ + void OTableConnection::Deselect() + { + m_bSelected = FALSE; + InvalidateConnection(); + } + + //------------------------------------------------------------------------ + BOOL OTableConnection::CheckHit( const Point& rMousePos ) const + { + ////////////////////////////////////////////////////////////////////// + // check if the point hit our line + ::std::vector<OConnectionLine*>::const_iterator aIter = ::std::find_if(m_vConnLine.begin(), + m_vConnLine.end(), + ::std::bind2nd(TConnectionLineCheckHitFunctor(),rMousePos)); + return aIter != m_vConnLine.end(); + } + + //------------------------------------------------------------------------ + bool OTableConnection::InvalidateConnection() + { + Rectangle rcBounding = GetBoundingRect(); + rcBounding.Bottom() += 1; + rcBounding.Right() += 1; + // ich glaube, dass sich Invalidate und Draw(Rectangle) nicht konsistent verhalten : jedenfalls waere dadurch zu + // erklaeren, warum ohne diesen Fake hier beim Loeschen einer Connection ein Strich an ihrem unteren Ende stehen bleibt : + // Invalidate erfasst dabei offensichtlich eine Pixelzeile weniger als Draw. + // Oder alles haengt ganz anders zusammen ... jedenfalls klappt es so ... + m_pParent->Invalidate( rcBounding, INVALIDATE_NOCHILDREN ); + + return true; + } + + //------------------------------------------------------------------------ + Rectangle OTableConnection::GetBoundingRect() const + { + ////////////////////////////////////////////////////////////////////// + // Aus allen Linien das umgebende Rechteck bestimmen + Rectangle aBoundingRect( Point(0,0), Point(0,0) ); + Rectangle aTempRect; + ::std::vector<OConnectionLine*>::const_iterator aEnd = m_vConnLine.end(); + for(::std::vector<OConnectionLine*>::const_iterator aIter = m_vConnLine.begin();aIter != aEnd;++aIter) + { + aTempRect = (*aIter)->GetBoundingRect(); + + ////////////////////////////////////////////////////////////////////// + // Ist das BoundingRect dieser Linie gueltig? + if( (aTempRect.GetWidth()!=1) && (aTempRect.GetHeight()!=1) ) + { + if( (aBoundingRect.GetWidth()==1) && (aBoundingRect.GetHeight()==1) ) + aBoundingRect = aTempRect; + else + aBoundingRect.Union( aTempRect ); + } + } + + return aBoundingRect; + } + + //------------------------------------------------------------------------ + void OTableConnection::Draw( const Rectangle& /*rRect*/ ) + { + ////////////////////////////////////////////////////////////////////// + // Linien zeichnen + ::std::for_each(m_vConnLine.begin(),m_vConnLine.end(),TConnectionLineDrawFunctor(m_pParent)); + } + // ----------------------------------------------------------------------------- +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/TableConnectionData.cxx b/dbaccess/source/ui/querydesign/TableConnectionData.cxx new file mode 100644 index 000000000000..263dab0e9593 --- /dev/null +++ b/dbaccess/source/ui/querydesign/TableConnectionData.cxx @@ -0,0 +1,197 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "TableConnectionData.hxx" +#include <tools/debug.hxx> +#include <comphelper/stl_types.hxx> + +using namespace dbaui; +using namespace comphelper; +//================================================================== +// class OTableConnectionData +//================================================================== +DBG_NAME(OTableConnectionData) +//------------------------------------------------------------------------ +OTableConnectionData::OTableConnectionData() +{ + DBG_CTOR(OTableConnectionData,NULL); + Init(); +} +// ----------------------------------------------------------------------------- +OTableConnectionData::OTableConnectionData(const TTableWindowData::value_type& _pReferencingTable + ,const TTableWindowData::value_type& _pReferencedTable + ,const String& rConnName ) + :m_pReferencingTable(_pReferencingTable) + ,m_pReferencedTable(_pReferencedTable) + ,m_aConnName( rConnName ) +{ + DBG_CTOR(OTableConnectionData,NULL); + Init(); +} +//------------------------------------------------------------------------ +void OTableConnectionData::Init() +{ + ////////////////////////////////////////////////////////////////////// + // LineDataList mit Defaults initialisieren + DBG_ASSERT(m_vConnLineData.size() == 0, "OTableConnectionData::Init() : nur mit leere Linienliste aufzurufen !"); + ResetConnLines(TRUE); + // das legt Defaults an +} +//------------------------------------------------------------------------ +OTableConnectionData::OTableConnectionData( const OTableConnectionData& rConnData ) +{ + DBG_CTOR(OTableConnectionData,NULL); + *this = rConnData; +} +//------------------------------------------------------------------------ +void OTableConnectionData::CopyFrom(const OTableConnectionData& rSource) +{ + *this = rSource; + // hier ziehe ich mich auf das (nicht-virtuelle) operator= zurueck, das nur meine Members kopiert +} + +//------------------------------------------------------------------------ +OTableConnectionData::~OTableConnectionData() +{ + DBG_DTOR(OTableConnectionData,NULL); + // LineDataList loeschen + OConnectionLineDataVec().swap(m_vConnLineData); +} + +//------------------------------------------------------------------------ +OTableConnectionData& OTableConnectionData::operator=( const OTableConnectionData& rConnData ) +{ + if (&rConnData == this) + return *this; + + m_pReferencingTable = rConnData.m_pReferencingTable; + m_pReferencedTable = rConnData.m_pReferencedTable; + m_aConnName = rConnData.GetConnName(); + + // clear line list + ResetConnLines(FALSE); + + // und kopieren + OConnectionLineDataVec* pLineData = const_cast<OTableConnectionData*>(&rConnData)->GetConnLineDataList(); + + OConnectionLineDataVec::const_iterator aIter = pLineData->begin(); + OConnectionLineDataVec::const_iterator aEnd = pLineData->end(); + for(;aIter != aEnd;++aIter) + m_vConnLineData.push_back(new OConnectionLineData(**aIter)); + + return *this; +} + +//------------------------------------------------------------------------ +BOOL OTableConnectionData::SetConnLine( USHORT nIndex, const String& rSourceFieldName, const String& rDestFieldName ) +{ + if (USHORT(m_vConnLineData.size()) < nIndex) + return FALSE; + // == ist noch erlaubt, das entspricht einem Append + + if (m_vConnLineData.size() == nIndex) + return AppendConnLine(rSourceFieldName, rDestFieldName); + + OConnectionLineDataRef pConnLineData = m_vConnLineData[nIndex]; + DBG_ASSERT(pConnLineData != NULL, "OTableConnectionData::SetConnLine : habe ungueltiges LineData-Objekt"); + + pConnLineData->SetSourceFieldName( rSourceFieldName ); + pConnLineData->SetDestFieldName( rDestFieldName ); + + return TRUE; +} + +//------------------------------------------------------------------------ +BOOL OTableConnectionData::AppendConnLine( const ::rtl::OUString& rSourceFieldName, const ::rtl::OUString& rDestFieldName ) +{ + OConnectionLineDataVec::iterator aIter = m_vConnLineData.begin(); + OConnectionLineDataVec::iterator aEnd = m_vConnLineData.end(); + for(;aIter != aEnd;++aIter) + { + if((*aIter)->GetDestFieldName() == rDestFieldName && (*aIter)->GetSourceFieldName() == rSourceFieldName) + break; + } + if(aIter == aEnd) + { + OConnectionLineDataRef pNew = new OConnectionLineData(rSourceFieldName, rDestFieldName); + if (!pNew.is()) + return FALSE; + + m_vConnLineData.push_back(pNew); + } + return TRUE; +} + +//------------------------------------------------------------------------ +void OTableConnectionData::ResetConnLines( BOOL /*bUseDefaults*/ ) +{ + OConnectionLineDataVec().swap(m_vConnLineData); +} + +//------------------------------------------------------------------------ +OConnectionLineDataRef OTableConnectionData::CreateLineDataObj() +{ + return new OConnectionLineData(); +} + +//------------------------------------------------------------------------ +OConnectionLineDataRef OTableConnectionData::CreateLineDataObj( const OConnectionLineData& rConnLineData ) +{ + return new OConnectionLineData( rConnLineData ); +} +// ----------------------------------------------------------------------------- +OTableConnectionData* OTableConnectionData::NewInstance() const +{ + return new OTableConnectionData(); +} +// ----------------------------------------------------------------------------- +void OTableConnectionData::normalizeLines() +{ + // noch ein wenig Normalisierung auf den LineDatas : leere Lines vom Anfang an das Ende verschieben + sal_Int32 nCount = m_vConnLineData.size(); + for(sal_Int32 i=0;i<nCount;) + { + if(!m_vConnLineData[i]->GetSourceFieldName().getLength() || !m_vConnLineData[i]->GetDestFieldName().getLength()) + { + OConnectionLineDataRef pData = m_vConnLineData[i]; + m_vConnLineData.erase(m_vConnLineData.begin()+i); + m_vConnLineData.push_back(pData); + --nCount; + } + else + ++i; + } +} +// ----------------------------------------------------------------------------- + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/TableFieldDescription.cxx b/dbaccess/source/ui/querydesign/TableFieldDescription.cxx new file mode 100644 index 000000000000..8edf83464b96 --- /dev/null +++ b/dbaccess/source/ui/querydesign/TableFieldDescription.cxx @@ -0,0 +1,242 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "TableFieldDescription.hxx" +#include <tools/debug.hxx> +#include <com/sun/star/sdbc/DataType.hpp> +#include <comphelper/namedvaluecollection.hxx> + +#include <functional> + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace comphelper; +using namespace dbaui; + +DBG_NAME(OTableFieldDesc) +//============================================================================== +OTableFieldDesc::OTableFieldDesc() + :m_pTabWindow(0) + ,m_eDataType(1000) + ,m_eFunctionType( FKT_NONE ) + ,m_eFieldType(TAB_NORMAL_FIELD) + ,m_eOrderDir( ORDER_NONE ) + ,m_nIndex(0) + ,m_nColWidth(0) + ,m_nColumnId((sal_uInt16)-1) + ,m_bGroupBy(sal_False) + ,m_bVisible(sal_False) +{ + DBG_CTOR(OTableFieldDesc,NULL); +} +//------------------------------------------------------------------------------ +OTableFieldDesc::OTableFieldDesc(const OTableFieldDesc& rRS) + : ::salhelper::SimpleReferenceObject() + +{ + DBG_CTOR(OTableFieldDesc,NULL); + *this = rRS; +} + +//------------------------------------------------------------------------------ +OTableFieldDesc::OTableFieldDesc(const ::rtl::OUString& rT, const ::rtl::OUString& rF ) + :m_pTabWindow(0) + ,m_eFunctionType( FKT_NONE ) + ,m_eOrderDir( ORDER_NONE ) + ,m_nColumnId((sal_uInt16)-1) + ,m_bGroupBy(sal_False) + ,m_bVisible(sal_False) +{ + DBG_CTOR(OTableFieldDesc,NULL); + SetField( rF ); SetTable( rT ); +} + +//------------------------------------------------------------------------------ +OTableFieldDesc::~OTableFieldDesc() +{ + DBG_DTOR(OTableFieldDesc,NULL); +} +//------------------------------------------------------------------------------ +OTableFieldDesc& OTableFieldDesc::operator=( const OTableFieldDesc& rRS ) +{ + if (&rRS == this) + return *this; + + m_aCriteria = rRS.GetCriteria(); + m_aTableName = rRS.GetTable(); + m_aAliasName = rRS.GetAlias(); // table range + m_aFieldName = rRS.GetField(); // column + m_aFieldAlias = rRS.GetFieldAlias(); // column alias + m_aFunctionName = rRS.GetFunction(); // Funktionsname + m_pTabWindow = rRS.GetTabWindow(); + m_eDataType = rRS.GetDataType(); + m_eFunctionType = rRS.GetFunctionType(); + m_eFieldType = rRS.GetFieldType(); + m_eOrderDir = rRS.GetOrderDir(); + m_nIndex = rRS.GetFieldIndex(); + m_nColWidth = rRS.GetColWidth(); + m_nColumnId = rRS.m_nColumnId; + m_bGroupBy = rRS.IsGroupBy(); + m_bVisible = rRS.IsVisible(); + + return *this; +} +//------------------------------------------------------------------------------ +sal_Bool OTableFieldDesc::operator==( const OTableFieldDesc& rDesc ) +{ + DBG_CHKTHIS(OTableFieldDesc,NULL); + + return ( m_eOrderDir != rDesc.GetOrderDir() || + m_eDataType != rDesc.GetDataType() || + m_aAliasName != rDesc.GetAlias() || + m_aFunctionName != rDesc.GetFunction() || + m_aFieldName != rDesc.GetField() || + m_aTableName != rDesc.GetTable() || + m_bGroupBy != rDesc.IsGroupBy() || + m_aCriteria != rDesc.GetCriteria() || + m_bVisible != rDesc.IsVisible() ); + +} + +//------------------------------------------------------------------------------ +void OTableFieldDesc::SetCriteria( sal_uInt16 nIdx, const ::rtl::OUString& rCrit) +{ + DBG_CHKTHIS(OTableFieldDesc,NULL); + if (nIdx < m_aCriteria.size()) + m_aCriteria[nIdx] = rCrit; + else + { + for(sal_Int32 i=m_aCriteria.size();i<nIdx;++i) + m_aCriteria.push_back( ::rtl::OUString()); + m_aCriteria.push_back(rCrit); + } +} + +//------------------------------------------------------------------------------ +::rtl::OUString OTableFieldDesc::GetCriteria( sal_uInt16 nIdx ) const +{ + DBG_CHKTHIS(OTableFieldDesc,NULL); + ::rtl::OUString aRetStr; + if( nIdx < m_aCriteria.size()) + aRetStr = m_aCriteria[nIdx]; + + return aRetStr; +} + +// ----------------------------------------------------------------------------- +namespace +{ + struct SelectPropertyValueAsString : public ::std::unary_function< PropertyValue, ::rtl::OUString > + { + ::rtl::OUString operator()( const PropertyValue& i_rPropValue ) const + { + ::rtl::OUString sValue; + OSL_VERIFY( i_rPropValue.Value >>= sValue ); + return sValue; + } + }; +} + +// ----------------------------------------------------------------------------- +void OTableFieldDesc::Load( const ::com::sun::star::beans::PropertyValue& i_rSettings, const bool i_bIncludingCriteria ) +{ + DBG_CHKTHIS(OTableFieldDesc,NULL); + + ::comphelper::NamedValueCollection aFieldDesc( i_rSettings.Value ); + m_aAliasName = aFieldDesc.getOrDefault( "AliasName", m_aAliasName ); + m_aTableName = aFieldDesc.getOrDefault( "TableName", m_aTableName ); + m_aFieldName = aFieldDesc.getOrDefault( "FieldName", m_aFieldName ); + m_aFieldAlias = aFieldDesc.getOrDefault( "FieldAlias", m_aFieldAlias ); + m_aFunctionName = aFieldDesc.getOrDefault( "FunctionName", m_aFunctionName ); + m_eDataType = aFieldDesc.getOrDefault( "DataType", m_eDataType ); + m_eFunctionType = aFieldDesc.getOrDefault( "FunctionType", m_eFunctionType ); + m_nColWidth = aFieldDesc.getOrDefault( "ColWidth", m_nColWidth ); + m_bGroupBy = aFieldDesc.getOrDefault( "GroupBy", m_bGroupBy ); + m_bVisible = aFieldDesc.getOrDefault( "Visible", m_bVisible ); + + m_eFieldType = static_cast< ETableFieldType >( aFieldDesc.getOrDefault( "FieldType", static_cast< sal_Int32 >( m_eFieldType ) ) ); + m_eOrderDir = static_cast< EOrderDir >( aFieldDesc.getOrDefault( "OrderDir", static_cast< sal_Int32 >( m_eOrderDir ) ) ); + + if ( i_bIncludingCriteria ) + { + const Sequence< PropertyValue > aCriteria( aFieldDesc.getOrDefault( "Criteria", Sequence< PropertyValue >() ) ); + m_aCriteria.resize( aCriteria.getLength() ); + ::std::transform( + aCriteria.getConstArray(), + aCriteria.getConstArray() + aCriteria.getLength(), + m_aCriteria.begin(), + SelectPropertyValueAsString() + ); + } +} +//------------------------------------------------------------------------------ +void OTableFieldDesc::Save( ::comphelper::NamedValueCollection& o_rSettings, const bool i_bIncludingCriteria ) +{ + DBG_CHKTHIS(OTableFieldDesc,NULL); + + o_rSettings.put( "AliasName", m_aAliasName ); + o_rSettings.put( "TableName", m_aTableName ); + o_rSettings.put( "FieldName", m_aFieldName ); + o_rSettings.put( "FieldAlias", m_aFieldAlias ); + o_rSettings.put( "FunctionName", m_aFunctionName ); + o_rSettings.put( "DataType", m_eDataType ); + o_rSettings.put( "FunctionType", (sal_Int32)m_eFunctionType ); + o_rSettings.put( "FieldType", (sal_Int32)m_eFieldType ); + o_rSettings.put( "OrderDir", (sal_Int32)m_eOrderDir ); + o_rSettings.put( "ColWidth", m_nColWidth ); + o_rSettings.put( "GroupBy", m_bGroupBy ); + o_rSettings.put( "Visible", m_bVisible ); + + if ( i_bIncludingCriteria ) + { + if ( !m_aCriteria.empty() ) + { + sal_Int32 c = 0; + Sequence< PropertyValue > aCriteria( m_aCriteria.size() ); + for ( ::std::vector< ::rtl::OUString >::const_iterator crit = m_aCriteria.begin(); + crit != m_aCriteria.end(); + ++crit, ++c + ) + { + aCriteria[c].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Criterion_" ) ) + ::rtl::OUString::valueOf( c ); + aCriteria[c].Value <<= *crit; + } + + o_rSettings.put( "Criteria", aCriteria ); + } + } +} +// ----------------------------------------------------------------------------- + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/TableFieldInfo.cxx b/dbaccess/source/ui/querydesign/TableFieldInfo.cxx new file mode 100644 index 000000000000..7ef432c32bd8 --- /dev/null +++ b/dbaccess/source/ui/querydesign/TableFieldInfo.cxx @@ -0,0 +1,57 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "TableFieldInfo.hxx" +#include <tools/debug.hxx> + +using namespace dbaui; +//================================================================== +// class OTableFieldInfo +//================================================================== + +DBG_NAME(OTableFieldInfo) +OTableFieldInfo::OTableFieldInfo() : + m_eDataType(1000) +{ + DBG_CTOR(OTableFieldInfo,NULL); + m_eFieldType = TAB_NORMAL_FIELD; +} + +//------------------------------------------------------------------------------ +OTableFieldInfo::~OTableFieldInfo() +{ + DBG_DTOR(OTableFieldInfo,NULL); +} + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/TableFieldInfo.hxx b/dbaccess/source/ui/querydesign/TableFieldInfo.hxx new file mode 100644 index 000000000000..090d71735665 --- /dev/null +++ b/dbaccess/source/ui/querydesign/TableFieldInfo.hxx @@ -0,0 +1,55 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_TABLEFIELDINFO_HXX +#define DBAUI_TABLEFIELDINFO_HXX + +#include "QEnumTypes.hxx" +#include <sal/types.h> + +namespace dbaui +{ + class OTableFieldInfo + { + private: + ETableFieldType m_eFieldType; + sal_Int32 m_eDataType; + + public: + OTableFieldInfo(); + ~OTableFieldInfo(); + + inline ETableFieldType GetKeyType() const { return m_eFieldType; } + inline void SetKey(ETableFieldType bKey=TAB_NORMAL_FIELD) { m_eFieldType = bKey; } + inline sal_Int32 GetDataType() const { return m_eDataType; } + inline void SetDataType(sal_Int32 eTyp) { m_eDataType = eTyp; } + }; +} +#endif // DBAUI_TABLEFIELDINFO_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/TableWindow.cxx b/dbaccess/source/ui/querydesign/TableWindow.cxx new file mode 100644 index 000000000000..13c0797033ed --- /dev/null +++ b/dbaccess/source/ui/querydesign/TableWindow.cxx @@ -0,0 +1,803 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "TableWindow.hxx" +#include "TableWindowListBox.hxx" +#include "QueryTableView.hxx" +#include "QueryDesignView.hxx" +#include "TableWindowData.hxx" +#include "imageprovider.hxx" +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/svapp.hxx> +#include <vcl/wall.hxx> + +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include "querycontroller.hxx" +#include "dbu_qry.hrc" +#include "dbustrings.hrc" +#include "Query.hrc" +#include <comphelper/extract.hxx> +#include "UITools.hxx" +#include "TableWindowAccess.hxx" +#include "browserids.hxx" +#include <connectivity/dbtools.hxx> + + +using namespace dbaui; +using namespace ::utl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::accessibility; + +#define TABWIN_SIZING_AREA 4 +#define LISTBOX_SCROLLING_AREA 6 +#define SCROLLING_TIMESPAN 500 + +#define TABWIN_WIDTH_MIN 90 +#define TABWIN_HEIGHT_MIN 80 + +//======================================================================== +// class OTableWindow +//======================================================================== +DBG_NAME(OTableWindow) +//------------------------------------------------------------------------------ +OTableWindow::OTableWindow( Window* pParent, const TTableWindowData::value_type& pTabWinData ) + : ::comphelper::OContainerListener(m_aMutex) + ,Window( pParent, WB_3DLOOK|WB_MOVEABLE ) + ,m_aTypeImage( this ) + ,m_aTitle( this ) + ,m_pListBox(NULL) + ,m_pAccessible(NULL) + ,m_pData( pTabWinData ) + ,m_nMoveCount(0) + ,m_nMoveIncrement(1) + ,m_nSizingFlags( SIZING_NONE ) + ,m_bActive( FALSE ) +{ + DBG_CTOR(OTableWindow,NULL); + + // Position und Groesse bestimmen + if( GetData()->HasPosition() ) + SetPosPixel( GetData()->GetPosition() ); + + if( GetData()->HasSize() ) + SetSizePixel( GetData()->GetSize() ); + + // Hintergrund setzen + const StyleSettings& aSystemStyle = Application::GetSettings().GetStyleSettings(); + SetBackground(Wallpaper(aSystemStyle.GetFaceColor())); + // und Textfarbe (obwohl ich eigentlich keinen Text habe, aber wer weiss, was + // abgeleitete Klassen machen) + SetTextColor(aSystemStyle.GetButtonTextColor()); + + EnableClipSiblings(); +} + +//------------------------------------------------------------------------------ +OTableWindow::~OTableWindow() +{ + DBG_DTOR(OTableWindow,NULL); + + if (m_pListBox) + { + OSL_ENSURE(m_pListBox->GetEntryCount()==0,"Forgot to call EmptyListbox()!"); + ::std::auto_ptr<Window> aTemp(m_pListBox); + m_pListBox = NULL; + } + if ( m_pContainerListener.is() ) + m_pContainerListener->dispose(); + + m_pAccessible = NULL; +} +// ----------------------------------------------------------------------------- +const OJoinTableView* OTableWindow::getTableView() const +{ + OSL_ENSURE(static_cast<OJoinTableView*>(GetParent()),"No OJoinTableView!"); + return static_cast<OJoinTableView*>(GetParent()); +} +// ----------------------------------------------------------------------------- +OJoinTableView* OTableWindow::getTableView() +{ + OSL_ENSURE(static_cast<OJoinTableView*>(GetParent()),"No OJoinTableView!"); + return static_cast<OJoinTableView*>(GetParent()); +} +// ----------------------------------------------------------------------------- +OJoinDesignView* OTableWindow::getDesignView() +{ + OSL_ENSURE(static_cast<OJoinDesignView*>(GetParent()->GetParent()->GetParent()),"No OJoinDesignView!"); + return static_cast<OJoinDesignView*>(GetParent()->GetParent()->GetParent()); +} +//------------------------------------------------------------------------------ +void OTableWindow::SetPosPixel( const Point& rNewPos ) +{ + Point aNewPosData = rNewPos + getTableView()->GetScrollOffset(); + GetData()->SetPosition( aNewPosData ); + Window::SetPosPixel( rNewPos ); +} + +//------------------------------------------------------------------------------ +void OTableWindow::SetSizePixel( const Size& rNewSize ) +{ + Size aOutSize(rNewSize); + if( aOutSize.Width() < TABWIN_WIDTH_MIN ) + aOutSize.Width() = TABWIN_WIDTH_MIN; + if( aOutSize.Height() < TABWIN_HEIGHT_MIN ) + aOutSize.Height() = TABWIN_HEIGHT_MIN; + + GetData()->SetSize( aOutSize ); + Window::SetSizePixel( aOutSize ); +} +//------------------------------------------------------------------------------ +void OTableWindow::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize ) +{ + SetPosPixel( rNewPos ); + SetSizePixel( rNewSize ); +} +//------------------------------------------------------------------------------ +OTableWindowListBox* OTableWindow::CreateListBox() +{ + return new OTableWindowListBox(this); +} + +//------------------------------------------------------------------------------ +BOOL OTableWindow::FillListBox() +{ + m_pListBox->Clear(); + if ( !m_pContainerListener.is() ) + { + Reference< XContainer> xContainer(m_pData->getColumns(),UNO_QUERY); + if ( xContainer.is() ) + m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer); + } + // mark all primary keys with special image + ModuleRes TmpRes(IMG_JOINS); + ImageList aImageList(TmpRes); + Image aPrimKeyImage = aImageList.GetImage(IMG_PRIMARY_KEY); + + if (GetData()->IsShowAll()) + { + SvLBoxEntry* pEntry = m_pListBox->InsertEntry( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")) ); + pEntry->SetUserData( createUserData(NULL,false) ); + } + + Reference<XNameAccess> xPKeyColumns; + try + { + xPKeyColumns = dbtools::getPrimaryKeyColumns_throw(m_pData->getTable()); + } + catch(Exception&) + { + OSL_ENSURE(0,"Exception occurred!"); + } + try + { + Reference< XNameAccess > xColumns = m_pData->getColumns(); + if( xColumns.is() ) + { + Sequence< ::rtl::OUString> aColumns = xColumns->getElementNames(); + const ::rtl::OUString* pIter = aColumns.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aColumns.getLength(); + + SvLBoxEntry* pEntry = NULL; + for (; pIter != pEnd; ++pIter) + { + bool bPrimaryKeyColumn = xPKeyColumns.is() && xPKeyColumns->hasByName( *pIter ); + // is this column in the primary key + if ( bPrimaryKeyColumn ) + pEntry = m_pListBox->InsertEntry(*pIter, aPrimKeyImage, aPrimKeyImage); + else + pEntry = m_pListBox->InsertEntry(*pIter); + + Reference<XPropertySet> xColumn(xColumns->getByName(*pIter),UNO_QUERY); + if ( xColumn.is() ) + pEntry->SetUserData( createUserData(xColumn,bPrimaryKeyColumn) ); + } + } + } + catch(Exception&) + { + OSL_ENSURE(0,"Exception occurred!"); + } + + return TRUE; +} +// ----------------------------------------------------------------------------- +void* OTableWindow::createUserData(const Reference< XPropertySet>& /*_xColumn*/,bool /*_bPrimaryKey*/) +{ + return NULL; +} +// ----------------------------------------------------------------------------- +void OTableWindow::deleteUserData(void*& _pUserData) +{ + OSL_ENSURE(!_pUserData,"INVALID call. Need to delete the userclass!"); + _pUserData = NULL; +} +//------------------------------------------------------------------------------ +void OTableWindow::clearListBox() +{ + if ( m_pListBox ) + { + SvLBoxEntry* pEntry = m_pListBox->First(); + + while(pEntry) + { + void* pUserData = pEntry->GetUserData(); + deleteUserData(pUserData); + SvLBoxEntry* pNextEntry = m_pListBox->Next(pEntry); + m_pListBox->GetModel()->Remove(pEntry); + pEntry = pNextEntry; + } + } +} + +//------------------------------------------------------------------------------ +void OTableWindow::impl_updateImage() +{ + ImageProvider aImageProvider( getDesignView()->getController().getConnection() ); + + Image aImage; + aImageProvider.getImages( GetComposedName(), m_pData->isQuery() ? DatabaseObject::QUERY : DatabaseObject::TABLE, aImage ); + + if ( !aImage ) + { + OSL_ENSURE( false, "OTableWindow::impl_updateImage: no images!" ); + return; + } + + m_aTypeImage.SetModeImage( aImage ); + m_aTypeImage.Show(); +} + +//------------------------------------------------------------------------------ +BOOL OTableWindow::Init() +{ + // create list box if necessary + if ( !m_pListBox ) + { + m_pListBox = CreateListBox(); + DBG_ASSERT( m_pListBox != NULL, "OTableWindow::Init() : CreateListBox hat NULL geliefert !" ); + m_pListBox->SetSelectionMode( MULTIPLE_SELECTION ); + } + + // Titel setzen + m_aTitle.SetText( m_pData->GetWinName() ); + m_aTitle.Show(); + + m_pListBox->Show(); + + // die Felder in die ListBox eintragen + clearListBox(); + BOOL bSuccess = FillListBox(); + if ( bSuccess ) + m_pListBox->SelectAll( FALSE ); + + impl_updateImage(); + + return bSuccess; +} +//------------------------------------------------------------------------------ +void OTableWindow::DataChanged(const DataChangedEvent& rDCEvt) +{ + if (rDCEvt.GetType() == DATACHANGED_SETTINGS) + { + // nehmen wir den worst-case an : die Farben haben sich geaendert, also + // mich anpassen + const StyleSettings& aSystemStyle = Application::GetSettings().GetStyleSettings(); + SetBackground(Wallpaper(Color(aSystemStyle.GetFaceColor()))); + SetTextColor(aSystemStyle.GetButtonTextColor()); + } +} +//------------------------------------------------------------------------------ +void OTableWindow::Paint( const Rectangle& rRect ) +{ + Rectangle aRect( Point(0,0), GetOutputSizePixel() ); + Window::Paint( rRect ); + Draw3DBorder( aRect ); +} + +//------------------------------------------------------------------------------ +void OTableWindow::Draw3DBorder(const Rectangle& rRect) +{ + // die Style-Settings des Systems fuer meine Farben + const StyleSettings& aSystemStyle = Application::GetSettings().GetStyleSettings(); + + // Schwarze Linie unten und rechts + SetLineColor(aSystemStyle.GetDarkShadowColor()); + DrawLine( rRect.BottomLeft(), rRect.BottomRight() ); + DrawLine( rRect.BottomRight(), rRect.TopRight() ); + + // Dunkelgraue Linie ueber der schwarzen + SetLineColor(aSystemStyle.GetShadowColor()); + Point aEHvector(1,1); + DrawLine( rRect.BottomLeft()+Point(1,-1), rRect.BottomRight() - aEHvector ); + DrawLine( rRect.BottomRight() - aEHvector, rRect.TopRight()+Point(-1,1) ); + + // Hellgraue Linie links und oben + SetLineColor(aSystemStyle.GetLightColor()); + DrawLine( rRect.BottomLeft()+Point(1,-2), rRect.TopLeft() + aEHvector ); + DrawLine( rRect.TopLeft() + aEHvector, rRect.TopRight()+Point(-2,1) ); +} +// ----------------------------------------------------------------------------- +Rectangle OTableWindow::getSizingRect(const Point& _rPos,const Size& _rOutputSize) const +{ + Rectangle aSizingRect = Rectangle( GetPosPixel(), GetSizePixel() ); + UINT16 nSizingFlags = GetSizingFlags(); + + if( nSizingFlags & SIZING_TOP ) + { + if( _rPos.Y() < 0 ) + aSizingRect.Top() = 0; + else + aSizingRect.Top() = _rPos.Y(); + } + + if( nSizingFlags & SIZING_BOTTOM ) + { + if( _rPos.Y() > _rOutputSize.Height() ) + aSizingRect.Bottom() = _rOutputSize.Height(); + else + aSizingRect.Bottom() = _rPos.Y(); + } + + + if( nSizingFlags & SIZING_RIGHT ) + { + if( _rPos.X() > _rOutputSize.Width() ) + aSizingRect.Right() = _rOutputSize.Width(); + else + aSizingRect.Right() = _rPos.X(); + } + + if( nSizingFlags & SIZING_LEFT ) + { + if( _rPos.X() < 0 ) + aSizingRect.Left() = 0; + else + aSizingRect.Left() = _rPos.X(); + } + return aSizingRect; +} +// ----------------------------------------------------------------------------- +void OTableWindow::setSizingFlag(const Point& _rPos) +{ + Size aOutSize = GetOutputSizePixel(); + ////////////////////////////////////////////////////////////////////// + // Flags anpassen, wenn Mauszeiger in sizingArea + m_nSizingFlags = SIZING_NONE; + + if( _rPos.X() < TABWIN_SIZING_AREA ) + m_nSizingFlags |= SIZING_LEFT; + + if( _rPos.Y() < TABWIN_SIZING_AREA ) + m_nSizingFlags |= SIZING_TOP; + + if( _rPos.X() > aOutSize.Width()-TABWIN_SIZING_AREA ) + m_nSizingFlags |= SIZING_RIGHT; + + if( _rPos.Y() > aOutSize.Height()-TABWIN_SIZING_AREA ) + m_nSizingFlags |= SIZING_BOTTOM; +} +//------------------------------------------------------------------------------ +void OTableWindow::MouseMove( const MouseEvent& rEvt ) +{ + Window::MouseMove(rEvt); + + OJoinTableView* pCont = getTableView(); + if (pCont->getDesignView()->getController().isReadOnly()) + return; + + Point aPos = rEvt.GetPosPixel(); + setSizingFlag(aPos); + Pointer aPointer; + + + ////////////////////////////////////////////////////////////////////// + // Mauszeiger anpassen, wenn Mauszeiger in sizingArea + switch( m_nSizingFlags ) + { + case SIZING_TOP: + case SIZING_BOTTOM: + aPointer = Pointer( POINTER_SSIZE ); + break; + + case SIZING_LEFT: + case SIZING_RIGHT: + aPointer = Pointer( POINTER_ESIZE ); + break; + + case SIZING_LEFT+SIZING_TOP: + case SIZING_RIGHT+SIZING_BOTTOM: + aPointer = Pointer( POINTER_SESIZE ); + break; + + case SIZING_RIGHT+SIZING_TOP: + case SIZING_LEFT+SIZING_BOTTOM: + aPointer = Pointer( POINTER_NESIZE ); + break; + } + + SetPointer( aPointer ); +} + +//------------------------------------------------------------------------------ +void OTableWindow::MouseButtonDown( const MouseEvent& rEvt ) +{ + ////////////////////////////////////////////////////////////////////// + // Wenn sizing, dann bekommt Parent die Nachricht, + // dass jetzt die Fenstergroesse seines Childs veraendert wird + if( m_nSizingFlags ) + getTableView()->BeginChildSizing( this, GetPointer() ); + + Window::MouseButtonDown( rEvt ); +} + + + +//------------------------------------------------------------------------------ +void OTableWindow::Resize() +{ + ////////////////////////////////////////////////////////////////////// + // Das Fenster darf nicht verschwinden, deshalb min. Groesse setzen + Size aOutSize = GetOutputSizePixel(); + aOutSize = Size(CalcZoom(aOutSize.Width()),CalcZoom(aOutSize.Height())); + + long nTitleHeight = CalcZoom( GetTextHeight() )+ CalcZoom( 4 ); + + ////////////////////////////////////////////////////////////////////// + // Titel und ListBox anpassen + long n5Pos = CalcZoom(5); + long nPositionX = n5Pos; + long nPositionY = n5Pos; + + // position the image which indicates the type + m_aTypeImage.SetPosPixel( Point( nPositionX, nPositionY ) ); + Size aImageSize( m_aTypeImage.GetImage().GetSizePixel() ); + m_aTypeImage.SetSizePixel( aImageSize ); + + if ( nTitleHeight < aImageSize.Height() ) + nTitleHeight = aImageSize.Height(); + + nPositionX += aImageSize.Width() + CalcZoom( 2 ); + m_aTitle.SetPosSizePixel( Point( nPositionX, nPositionY ), Size( aOutSize.Width() - nPositionX - n5Pos, nTitleHeight ) ); + + long nTitleToList = CalcZoom( 3 ); + + m_pListBox->SetPosSizePixel( + Point( n5Pos, nPositionY + nTitleHeight + nTitleToList ), + Size( aOutSize.Width() - 2 * n5Pos, aOutSize.Height() - ( nPositionY + nTitleHeight + nTitleToList ) - n5Pos ) + ); + + Window::Invalidate(); +} + +//------------------------------------------------------------------------------ +void OTableWindow::SetBoldTitle( BOOL bBold ) +{ + Font aFont = m_aTitle.GetFont(); + aFont.SetWeight( bBold?WEIGHT_BOLD:WEIGHT_NORMAL ); + m_aTitle.SetFont( aFont ); + m_aTitle.Invalidate(); +} + +//------------------------------------------------------------------------------ +void OTableWindow::GetFocus() +{ + Window::GetFocus(); + // we have to forward the focus to our listbox to enable keystokes + if(m_pListBox) + m_pListBox->GrabFocus(); +} +// ----------------------------------------------------------------------------- +void OTableWindow::setActive(sal_Bool _bActive) +{ + SetBoldTitle( _bActive ); + m_bActive = _bActive; + if (!_bActive && m_pListBox && m_pListBox->GetSelectionCount() != 0) + m_pListBox->SelectAll(FALSE); +} + +//------------------------------------------------------------------------------ +void OTableWindow::Remove() +{ + ////////////////////////////////////////////////////////////////// + // Fenster loeschen + OJoinTableView* pTabWinCont = getTableView(); + pTabWinCont->RemoveTabWin( this ); + pTabWinCont->Invalidate(); +} +//------------------------------------------------------------------------------ +BOOL OTableWindow::HandleKeyInput( const KeyEvent& rEvt ) +{ + const KeyCode& rCode = rEvt.GetKeyCode(); + USHORT nCode = rCode.GetCode(); + BOOL bShift = rCode.IsShift(); + BOOL bCtrl = rCode.IsMod1(); + + BOOL bHandle = FALSE; + + if( !bCtrl && !bShift && (nCode==KEY_DELETE) ) + { + Remove(); + bHandle = TRUE; + } + return bHandle; +} + +//------------------------------------------------------------------------------ +BOOL OTableWindow::ExistsAConn() const +{ + return getTableView()->ExistsAConn(this); +} +//------------------------------------------------------------------------------ +void OTableWindow::EnumValidFields(::std::vector< ::rtl::OUString>& arrstrFields) +{ + arrstrFields.clear(); + // diese Default-Implementierung zaehlt einfach alles auf, was es in der ListBox gibt ... fuer anderes Verhalten ueberschreiben + if ( m_pListBox ) + { + arrstrFields.reserve(m_pListBox->GetEntryCount()); + SvLBoxEntry* pEntryLoop = m_pListBox->First(); + while (pEntryLoop) + { + arrstrFields.push_back(m_pListBox->GetEntryText(pEntryLoop)); + pEntryLoop = m_pListBox->Next(pEntryLoop); + } + } +} +// ----------------------------------------------------------------------------- +void OTableWindow::StateChanged( StateChangedType nType ) +{ + Window::StateChanged( nType ); + + if ( nType == STATE_CHANGE_ZOOM ) + { + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + Font aFont = rStyleSettings.GetGroupFont(); + if ( IsControlFont() ) + aFont.Merge( GetControlFont() ); + SetZoomedPointFont( aFont ); + + m_aTitle.SetZoom(GetZoom()); + m_pListBox->SetZoom(GetZoom()); + Resize(); + Invalidate(); + } +} +// ----------------------------------------------------------------------------- +Reference< XAccessible > OTableWindow::CreateAccessible() +{ + OTableWindowAccess* pAccessible = new OTableWindowAccess(this); + m_pAccessible = pAccessible; + return pAccessible; +} +// ----------------------------------------------------------------------------- +void OTableWindow::Command(const CommandEvent& rEvt) +{ + switch (rEvt.GetCommand()) + { + case COMMAND_CONTEXTMENU: + { + OJoinController& rController = getDesignView()->getController(); + if(!rController.isReadOnly() && rController.isConnected()) + { + Point ptWhere; + if ( rEvt.IsMouseEvent() ) + ptWhere = rEvt.GetMousePosPixel(); + else + { + SvLBoxEntry* pCurrent = m_pListBox->GetCurEntry(); + if ( pCurrent ) + ptWhere = m_pListBox->GetEntryPosition(pCurrent); + else + ptWhere = m_aTitle.GetPosPixel(); + } + + PopupMenu aContextMenu(ModuleRes(RID_MENU_JOINVIEW_TABLE)); + switch (aContextMenu.Execute(this, ptWhere)) + { + case SID_DELETE: + Remove(); + break; + } + } + break; + } + default: + Window::Command(rEvt); + } +} +// ----------------------------------------------------------------------------- +long OTableWindow::PreNotify(NotifyEvent& rNEvt) +{ + BOOL bHandled = FALSE; + switch (rNEvt.GetType()) + { + case EVENT_KEYINPUT: + { + if ( getDesignView()->getController().isReadOnly() ) + break; + + const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent(); + const KeyCode& rCode = pKeyEvent->GetKeyCode(); + if ( rCode.IsMod1() ) + { + Point aStartPoint = GetPosPixel(); + if ( rCode.IsShift() ) + { + aStartPoint.X() = GetSizePixel().Width(); + aStartPoint.Y() = GetSizePixel().Height(); + } + + switch( rCode.GetCode() ) + { + case KEY_DOWN: + bHandled = TRUE; + aStartPoint.Y() += m_nMoveIncrement; + break; + case KEY_UP: + bHandled = TRUE; + aStartPoint.Y() += -m_nMoveIncrement; + break; + case KEY_LEFT: + bHandled = TRUE; + aStartPoint.X() += -m_nMoveIncrement; + break; + case KEY_RIGHT: + bHandled = TRUE; + aStartPoint.X() += m_nMoveIncrement; + break; + } + if ( bHandled ) + { + if ( rCode.IsShift() ) + { + OJoinTableView* pView = getTableView(); + Point ptOld = GetPosPixel(); + Size aSize = pView->getRealOutputSize(); + Size aNewSize(aStartPoint.X(),aStartPoint.Y()); + if ( ((ptOld.X() + aNewSize.Width()) <= aSize.Width()) + && ((ptOld.Y() + aNewSize.Height()) <= aSize.Height()) ) + { + if ( aNewSize.Width() < TABWIN_WIDTH_MIN ) + aNewSize.Width() = TABWIN_WIDTH_MIN; + if ( aNewSize.Height() < TABWIN_HEIGHT_MIN ) + aNewSize.Height() = TABWIN_HEIGHT_MIN; + + Size szOld = GetSizePixel(); + + aNewSize = Size(pView->CalcZoom(aNewSize.Width()),pView->CalcZoom(aNewSize.Height())); + SetPosSizePixel( ptOld, aNewSize ); + pView->TabWinSized(this, ptOld, szOld); + Invalidate( INVALIDATE_NOCHILDREN ); + } + } + else + { + // remember how often the user moved our window + ++m_nMoveCount; + if( m_nMoveCount == 5 ) + m_nMoveIncrement = 10; + else if( m_nMoveCount > 15 ) + m_nMoveCount = m_nMoveIncrement = 20; + + Point aOldDataPoint = GetData()->GetPosition(); + Point aNewDataPoint = aStartPoint + getTableView()->GetScrollOffset(); + if ( aNewDataPoint.X() > -1 && aNewDataPoint.Y() > -1 ) + { + OJoinTableView* pView = getTableView(); + if ( pView->isMovementAllowed(aNewDataPoint, GetData()->GetSize()) ) + { + SetPosPixel(aStartPoint); + + // aNewDataPoint can not be used here because SetPosPixel reset it + pView->EnsureVisible(GetData()->GetPosition(), GetData()->GetSize()); + pView->TabWinMoved(this,aOldDataPoint); + Invalidate(INVALIDATE_NOCHILDREN); + getDesignView()->getController().setModified( sal_True ); + } + else + { + m_nMoveCount = 0; // reset our movement count + m_nMoveIncrement = 1; + } + } + else + { + m_nMoveCount = 0; // reset our movement count + m_nMoveIncrement = 1; + } + } + resetSizingFlag(); + } + else + { + m_nMoveCount = 0; // reset our movement count + m_nMoveIncrement = 1; + } + } + else + { + m_nMoveCount = 0; // reset our movement count + m_nMoveIncrement = 1; + } + } + break; + case EVENT_KEYUP: + { + const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent(); + const KeyCode& rCode = pKeyEvent->GetKeyCode(); + USHORT nKeyCode = rCode.GetCode(); + if ( rCode.IsMod2() && nKeyCode != KEY_UP && nKeyCode != KEY_DOWN && nKeyCode != KEY_LEFT && nKeyCode != KEY_RIGHT ) + { + m_nMoveCount = 0; // reset our movement count + m_nMoveIncrement = 1; + } + } + break; + } + if (!bHandled) + return Window::PreNotify(rNEvt); + return 1L; +} +// ----------------------------------------------------------------------------- +String OTableWindow::getTitle() const +{ + return m_aTitle.GetText(); +} +// ----------------------------------------------------------------------------- +void OTableWindow::_elementInserted( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException) +{ + FillListBox(); +} +// ----------------------------------------------------------------------------- +void OTableWindow::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException) +{ + FillListBox(); +} +// ----------------------------------------------------------------------------- +void OTableWindow::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException) +{ + FillListBox(); +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/TableWindowAccess.cxx b/dbaccess/source/ui/querydesign/TableWindowAccess.cxx new file mode 100644 index 000000000000..44b3953b57e8 --- /dev/null +++ b/dbaccess/source/ui/querydesign/TableWindowAccess.cxx @@ -0,0 +1,294 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "TableWindowAccess.hxx" +#include "JAccess.hxx" +#include "TableWindow.hxx" +#include "TableWindowListBox.hxx" +#include "JoinDesignView.hxx" +#include "JoinController.hxx" +#include "JoinTableView.hxx" +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleRelationType.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <comphelper/sequence.hxx> +#include "dbu_qry.hrc" + + +namespace dbaui +{ + using namespace ::com::sun::star::accessibility; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star; + + OTableWindowAccess::OTableWindowAccess(OTableWindow* _pTable) + :VCLXAccessibleComponent(_pTable->GetComponentInterface().is() ? _pTable->GetWindowPeer() : NULL) + ,m_pTable(_pTable) + { + } + // ----------------------------------------------------------------------------- + void SAL_CALL OTableWindowAccess::disposing() + { + m_pTable = NULL; + VCLXAccessibleComponent::disposing(); + } + // ----------------------------------------------------------------------------- + void OTableWindowAccess::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) + { + if ( rVclWindowEvent.GetId() == VCLEVENT_OBJECT_DYING ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_pTable = NULL; + } + + VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent ); + } + // ----------------------------------------------------------------------------- + Any SAL_CALL OTableWindowAccess::queryInterface( const Type& aType ) throw (RuntimeException) + { + Any aRet(VCLXAccessibleComponent::queryInterface( aType )); + return aRet.hasValue() ? aRet : OTableWindowAccess_BASE::queryInterface( aType ); + } + // ----------------------------------------------------------------------------- + Sequence< Type > SAL_CALL OTableWindowAccess::getTypes( ) throw (RuntimeException) + { + return ::comphelper::concatSequences(VCLXAccessibleComponent::getTypes(),OTableWindowAccess_BASE::getTypes()); + } + // ----------------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OTableWindowAccess::getImplementationName() throw(RuntimeException) + { + return getImplementationName_Static(); + } + // ----------------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OTableWindowAccess::getSupportedServiceNames() throw(RuntimeException) + { + return getSupportedServiceNames_Static(); + } + // ----------------------------------------------------------------------------- + // XServiceInfo - static methods + Sequence< ::rtl::OUString > OTableWindowAccess::getSupportedServiceNames_Static(void) throw( RuntimeException ) + { + Sequence< ::rtl::OUString > aSupported(2); + aSupported[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.Accessible")); + aSupported[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleContext")); + return aSupported; + } + // ----------------------------------------------------------------------------- + ::rtl::OUString OTableWindowAccess::getImplementationName_Static(void) throw( RuntimeException ) + { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.dbu.TableWindowAccessibility")); + } + // ----------------------------------------------------------------------------- + // XAccessibleContext + sal_Int32 SAL_CALL OTableWindowAccess::getAccessibleChildCount( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + sal_Int32 nCount = 0; + if(m_pTable) + { + if(m_pTable->GetTitleCtrl()) + ++nCount; + if(m_pTable->GetListBox()) + ++nCount; + } + return nCount; + } + // ----------------------------------------------------------------------------- + Reference< XAccessible > SAL_CALL OTableWindowAccess::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException,RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + Reference< XAccessible > aRet; + if(m_pTable) + { + switch(i) + { + case 0: + if(m_pTable->GetTitleCtrl()) + { + aRet = m_pTable->GetTitleCtrl()->GetAccessible(); + break; + } // fall through if title control does not exist + case 1: + if(m_pTable->GetListBox()) + aRet = m_pTable->GetListBox()->GetAccessible(); + break; + default: + throw IndexOutOfBoundsException(); + } + } + return aRet; + } + // ----------------------------------------------------------------------------- + sal_Int32 SAL_CALL OTableWindowAccess::getAccessibleIndexInParent( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + sal_Int32 nIndex = -1; + if( m_pTable ) + { + // search the postion of our table window in the table window map + OJoinTableView::OTableWindowMap* pMap = m_pTable->getTableView()->GetTabWinMap(); + OJoinTableView::OTableWindowMap::iterator aIter = pMap->begin(); + OJoinTableView::OTableWindowMap::iterator aEnd = pMap->end(); + for (nIndex = 0; aIter != aEnd && aIter->second != m_pTable; ++nIndex,++aIter) + ; + nIndex = aIter != aEnd ? nIndex : -1; + } + return nIndex; + } + // ----------------------------------------------------------------------------- + sal_Int16 SAL_CALL OTableWindowAccess::getAccessibleRole( ) throw (RuntimeException) + { + return AccessibleRole::PANEL; // ? or may be an AccessibleRole::WINDOW + } + // ----------------------------------------------------------------------------- + Reference< XAccessibleRelationSet > SAL_CALL OTableWindowAccess::getAccessibleRelationSet( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return this; + } + // ----------------------------------------------------------------------------- + // XAccessibleComponent + Reference< XAccessible > SAL_CALL OTableWindowAccess::getAccessibleAtPoint( const awt::Point& _aPoint ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + Reference< XAccessible > aRet; + if( m_pTable ) + { + Point aPoint(_aPoint.X,_aPoint.Y); + Rectangle aRect(m_pTable->GetDesktopRectPixel()); + if( aRect.IsInside(aPoint) ) + aRet = this; + else if( m_pTable->GetListBox()->GetDesktopRectPixel().IsInside(aPoint)) + aRet = m_pTable->GetListBox()->GetAccessible(); + } + return aRet; + } + // ----------------------------------------------------------------------------- + Reference< XAccessible > OTableWindowAccess::getParentChild(sal_Int32 _nIndex) + { + Reference< XAccessible > xReturn; + Reference< XAccessible > xParent = getAccessibleParent(); + if ( xParent.is() ) + { + Reference< XAccessibleContext > xParentContext = xParent->getAccessibleContext(); + if ( xParentContext.is() ) + { + xReturn = xParentContext->getAccessibleChild(_nIndex); + } + } + return xReturn; + } + // ----------------------------------------------------------------------------- + + sal_Int32 SAL_CALL OTableWindowAccess::getRelationCount( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return m_pTable ? m_pTable->getTableView()->getConnectionCount(m_pTable) : sal_Int32(0); + } + // ----------------------------------------------------------------------------- + AccessibleRelation SAL_CALL OTableWindowAccess::getRelation( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if( nIndex < 0 || nIndex >= getRelationCount() ) + throw IndexOutOfBoundsException(); + + AccessibleRelation aRet; + if( m_pTable ) + { + OJoinTableView* pView = m_pTable->getTableView(); + ::std::vector<OTableConnection*>::const_iterator aIter = pView->getTableConnections(m_pTable) + nIndex; + aRet.TargetSet.realloc(1); + aRet.TargetSet[0] = getParentChild(aIter - pView->getTableConnections()->begin()); + aRet.RelationType = AccessibleRelationType::CONTROLLER_FOR; + } + return aRet; + } + // ----------------------------------------------------------------------------- + sal_Bool SAL_CALL OTableWindowAccess::containsRelation( sal_Int16 aRelationType ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return AccessibleRelationType::CONTROLLER_FOR == aRelationType + && m_pTable && m_pTable->getTableView()->ExistsAConn(m_pTable); + } + // ----------------------------------------------------------------------------- + AccessibleRelation SAL_CALL OTableWindowAccess::getRelationByType( sal_Int16 aRelationType ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if( AccessibleRelationType::CONTROLLER_FOR == aRelationType && m_pTable) + { + OJoinTableView* pView = m_pTable->getTableView(); + const ::std::vector<OTableConnection*>* pConnectionList = pView->getTableConnections(); + + ::std::vector<OTableConnection*>::const_iterator aIter = pView->getTableConnections(m_pTable); + ::std::vector<OTableConnection*>::const_iterator aEnd = pConnectionList->end(); + ::std::vector< Reference<XInterface> > aRelations; + aRelations.reserve(5); // just guessing + for (; aIter != aEnd ; ++aIter ) + aRelations.push_back(getParentChild(aIter - pConnectionList->begin())); + + Reference<XInterface> *pRelations = aRelations.empty() ? 0 : &aRelations[0]; + Sequence< Reference<XInterface> > aSeq(pRelations, aRelations.size()); + return AccessibleRelation(AccessibleRelationType::CONTROLLER_FOR,aSeq); + } + return AccessibleRelation(); + } + // ----------------------------------------------------------------------------- + sal_Bool OTableWindowAccess::isEditable() const + { + return m_pTable && !m_pTable->getTableView()->getDesignView()->getController().isReadOnly(); + } + // ----------------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OTableWindowAccess::getTitledBorderText( ) throw (RuntimeException) + { + return getAccessibleName( ); + } + // ----------------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OTableWindowAccess::getAccessibleName( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + ::rtl::OUString sAccessibleName; + if ( m_pTable ) + sAccessibleName = m_pTable->getTitle(); + return sAccessibleName; + } + // ----------------------------------------------------------------------------- + Reference< XAccessibleContext > SAL_CALL OTableWindowAccess::getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException) + { + return this; + } + // ----------------------------------------------------------------------------- + +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/TableWindowData.cxx b/dbaccess/source/ui/querydesign/TableWindowData.cxx new file mode 100644 index 000000000000..6a9d63372a88 --- /dev/null +++ b/dbaccess/source/ui/querydesign/TableWindowData.cxx @@ -0,0 +1,156 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "TableWindowData.hxx" +#include <tools/debug.hxx> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> + +using namespace dbaui; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; + +//================================================================== +// class OTableWindowData +//================================================================== +DBG_NAME(OTableWindowData) +//------------------------------------------------------------------------------ +OTableWindowData::OTableWindowData( const Reference< XPropertySet>& _xTable + ,const ::rtl::OUString& _rComposedName + ,const ::rtl::OUString& rTableName + ,const ::rtl::OUString& rWinName ) + :m_xTable(_xTable) + ,m_aTableName( rTableName ) + ,m_aWinName( rWinName ) + ,m_sComposedName(_rComposedName) + ,m_aPosition( Point(-1,-1) ) + ,m_aSize( Size(-1,-1) ) + ,m_bShowAll( TRUE ) + ,m_bIsQuery(false) + ,m_bIsValid(true) +{ + DBG_CTOR(OTableWindowData,NULL); + if( !m_aWinName.getLength() ) + m_aWinName = m_aTableName; + + listen(); +} + +//------------------------------------------------------------------------------ +OTableWindowData::~OTableWindowData() +{ + DBG_DTOR(OTableWindowData,NULL); + Reference<XComponent> xComponent( m_xTable, UNO_QUERY ); + if ( xComponent.is() ) + stopComponentListening( xComponent ); +} + +//------------------------------------------------------------------------------ +BOOL OTableWindowData::HasPosition() const +{ + return ( (m_aPosition.X() != -1) && (m_aPosition.Y() != -1) ); +} + +//------------------------------------------------------------------------------ +BOOL OTableWindowData::HasSize() const +{ + return ( (m_aSize.Width() != -1) && (m_aSize.Height() !=-1) ); +} +// ----------------------------------------------------------------------------- +void OTableWindowData::_disposing( const ::com::sun::star::lang::EventObject& /*_rSource*/ ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + // it doesn't matter which one was disposed + m_xColumns.clear(); + m_xKeys.clear(); + m_xTable.clear(); +} +// ----------------------------------------------------------------------------- +bool OTableWindowData::init(const Reference< XConnection >& _xConnection,bool _bAllowQueries) +{ + OSL_ENSURE(!m_xTable.is(),"We are already connected to a table!"); + + ::osl::MutexGuard aGuard( m_aMutex ); + + Reference< XQueriesSupplier > xSupQueries( _xConnection, UNO_QUERY_THROW ); + Reference< XNameAccess > xQueries( xSupQueries->getQueries(), UNO_QUERY_THROW ); + bool bIsKnownQuery = _bAllowQueries && xQueries->hasByName( m_sComposedName ); + + Reference< XTablesSupplier > xSupTables( _xConnection, UNO_QUERY_THROW ); + Reference< XNameAccess > xTables( xSupTables->getTables(), UNO_QUERY_THROW ); + bool bIsKnownTable = xTables->hasByName( m_sComposedName ); + + if ( bIsKnownQuery ) + m_xTable.set( xQueries->getByName( m_sComposedName ), UNO_QUERY ); + else if ( bIsKnownTable ) + m_xTable.set( xTables->getByName( m_sComposedName ), UNO_QUERY ); + else + m_bIsValid = false; + + // if we survived so far, we know whether it's a query + m_bIsQuery = bIsKnownQuery; + + listen(); + + Reference< XIndexAccess > xColumnsAsIndex( m_xColumns,UNO_QUERY ); + return xColumnsAsIndex.is() && ( xColumnsAsIndex->getCount() > 0 ); +} +// ----------------------------------------------------------------------------- +void OTableWindowData::listen() +{ + if ( m_xTable.is() ) + { + // listen for the object being disposed + Reference<XComponent> xComponent( m_xTable, UNO_QUERY ); + if ( xComponent.is() ) + startComponentListening( xComponent ); + + // obtain the columns + Reference< XColumnsSupplier > xColumnsSups( m_xTable, UNO_QUERY); + if ( xColumnsSups.is() ) + m_xColumns = xColumnsSups->getColumns(); + + Reference<XKeysSupplier> xKeySup(m_xTable,UNO_QUERY); + if ( xKeySup.is() ) + m_xKeys = xKeySup->getKeys(); + } +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/TableWindowListBox.cxx b/dbaccess/source/ui/querydesign/TableWindowListBox.cxx new file mode 100644 index 000000000000..b324c9263097 --- /dev/null +++ b/dbaccess/source/ui/querydesign/TableWindowListBox.cxx @@ -0,0 +1,402 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "TableWindowListBox.hxx" +#include "TableWindow.hxx" +#include "QueryDesignView.hxx" +#include "QueryTableView.hxx" +#include "querycontroller.hxx" +#include "JoinExchange.hxx" +#include <tools/debug.hxx> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include <svx/dbexch.hrc> +#include <vcl/svapp.hxx> + +using namespace dbaui; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::datatransfer; + +OJoinExchangeData::OJoinExchangeData(OTableWindowListBox* pBox) + : pListBox(pBox) + , pEntry(pBox->FirstSelected()) +{ } + +const ULONG SCROLLING_TIMESPAN = 500; +const long LISTBOX_SCROLLING_AREA = 6; +//================================================================== +// class OTableWindowListBox +//================================================================== +DBG_NAME(OTableWindowListBox) +//------------------------------------------------------------------------------ +OTableWindowListBox::OTableWindowListBox( OTableWindow* pParent ) + :SvTreeListBox( pParent, WB_HASBUTTONS | WB_BORDER) + ,m_aMousePos( Point(0,0) ) + ,m_pTabWin( pParent ) + ,m_nDropEvent(0) + ,m_nUiEvent(0) + ,m_bReallyScrolled( sal_False ) +{ + DBG_CTOR(OTableWindowListBox,NULL); + m_aScrollTimer.SetTimeout( SCROLLING_TIMESPAN ); + SetDoubleClickHdl( LINK(this, OTableWindowListBox, OnDoubleClick) ); + + SetSelectionMode(SINGLE_SELECTION); + + SetHighlightRange( ); +} + +//------------------------------------------------------------------------------ +void OTableWindowListBox::dragFinished( ) +{ + // first show the error msg when existing + m_pTabWin->getDesignView()->getController().showError(m_pTabWin->getDesignView()->getController().clearOccurredError()); + // second look for ui activities which should happen after d&d + if (m_nUiEvent) + Application::RemoveUserEvent(m_nUiEvent); + m_nUiEvent = Application::PostUserEvent(LINK(this, OTableWindowListBox, LookForUiHdl)); +} + +//------------------------------------------------------------------------------ +OTableWindowListBox::~OTableWindowListBox() +{ + DBG_DTOR(OTableWindowListBox,NULL); + if (m_nDropEvent) + Application::RemoveUserEvent(m_nDropEvent); + if (m_nUiEvent) + Application::RemoveUserEvent(m_nUiEvent); + if( m_aScrollTimer.IsActive() ) + m_aScrollTimer.Stop(); + m_pTabWin = NULL; +} + +//------------------------------------------------------------------------------ +SvLBoxEntry* OTableWindowListBox::GetEntryFromText( const String& rEntryText ) +{ + ////////////////////////////////////////////////////////////////////// + // Liste durchiterieren + SvTreeList* pTreeList = GetModel(); + SvLBoxEntry* pEntry = (SvLBoxEntry*)pTreeList->First(); + OJoinDesignView* pView = m_pTabWin->getDesignView(); + OJoinController& rController = pView->getController(); + + BOOL bCase = FALSE; + try + { + Reference<XConnection> xConnection = rController.getConnection(); + if(xConnection.is()) + { + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + if(xMeta.is()) + bCase = xMeta->supportsMixedCaseQuotedIdentifiers(); + } + while( pEntry ) + { + if((bCase ? rEntryText == GetEntryText(pEntry) : rEntryText.EqualsIgnoreCaseAscii(GetEntryText(pEntry)))) + { + return pEntry; + } + pEntry = (SvLBoxEntry*)pTreeList->Next( pEntry ); + } + } + catch(SQLException&) + { + } + + return NULL; +} + +//------------------------------------------------------------------------------ +void OTableWindowListBox::NotifyScrolled() +{ + m_bReallyScrolled = TRUE; +} + +//------------------------------------------------------------------------------ +void OTableWindowListBox::NotifyEndScroll() +{ + if (m_bReallyScrolled) + // die Verbindungen, die diese Tabelle eventuell hat, muessen neu gezeichnet werden + m_pTabWin->getTableView()->Invalidate(INVALIDATE_NOCHILDREN); + // ohne das INVALIDATE_NOCHILDREN wuerden auch alle Tabellen neu gezeichnet werden, + // sprich : es flackert + m_bReallyScrolled = FALSE; +} + +//------------------------------------------------------------------------------ +long OTableWindowListBox::PreNotify(NotifyEvent& rNEvt) +{ + BOOL bHandled = FALSE; + switch (rNEvt.GetType()) + { + case EVENT_KEYINPUT: + { + const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent(); + const KeyCode& rCode = pKeyEvent->GetKeyCode(); + + if (rCode.GetCode() != KEY_RETURN) + { + if(m_pTabWin) + { + bHandled = m_pTabWin->HandleKeyInput(*pKeyEvent); + } + break; + } + + if (rCode.IsMod1() || rCode.IsMod2() || rCode.IsShift()) + break; + if (FirstSelected()) + static_cast<OTableWindow*>(Window::GetParent())->OnEntryDoubleClicked(FirstSelected()); + } + break; + } + + if (!bHandled) + return SvTreeListBox::PreNotify(rNEvt); + return 1L; +} + +//------------------------------------------------------------------------------ +IMPL_LINK( OTableWindowListBox, ScrollUpHdl, SvTreeListBox*, /*pBox*/ ) +{ + SvLBoxEntry* pEntry = GetEntry( m_aMousePos ); + if( !pEntry ) + return 0; + + if( pEntry != Last() ) + { + ScrollOutputArea( -1 ); + pEntry = GetEntry( m_aMousePos ); + Select( pEntry, TRUE ); + } + + return 0; +} + +//------------------------------------------------------------------------------ +IMPL_LINK( OTableWindowListBox, ScrollDownHdl, SvTreeListBox*, /*pBox*/ ) +{ + SvLBoxEntry* pEntry = GetEntry( m_aMousePos ); + if( !pEntry ) + return 0; + + if( pEntry != Last() ) + { + ScrollOutputArea( 1 ); + pEntry = GetEntry( m_aMousePos ); + Select( pEntry, TRUE ); + } + + return 0; +} + +//------------------------------------------------------------------------------ +void OTableWindowListBox::StartDrag( sal_Int8 /*nAction*/, const Point& /*rPosPixel*/ ) +{ + OJoinTableView* pCont = m_pTabWin->getTableView(); + if (!pCont->getDesignView()->getController().isReadOnly() && pCont->getDesignView()->getController().isConnected()) + { + // #100271# OJ asterix was not allowed to be copied to selection browsebox + sal_Bool bFirstNotAllowed = FirstSelected() == First() && m_pTabWin->GetData()->IsShowAll(); + EndSelection(); + // create a description of the source + OJoinExchangeData jxdSource(this); + // put it into a exchange object + OJoinExchObj* pJoin = new OJoinExchObj(jxdSource,bFirstNotAllowed); + Reference< XTransferable > xEnsureDelete(pJoin); + pJoin->StartDrag(this, DND_ACTION_LINK, this); + } +} + +//------------------------------------------------------------------------------ +sal_Int8 OTableWindowListBox::AcceptDrop( const AcceptDropEvent& _rEvt ) +{ + sal_Int8 nDND_Action = DND_ACTION_NONE; + // check the format + if ( !OJoinExchObj::isFormatAvailable(GetDataFlavorExVector(),SOT_FORMATSTR_ID_SBA_TABID) // this means that the first entry is to be draged + && OJoinExchObj::isFormatAvailable(GetDataFlavorExVector(),SOT_FORMATSTR_ID_SBA_JOIN) ) + { // don't drop into the window if it's the drag source itself + + // remove the selection if the dragging operation is leaving the window + if (_rEvt.mbLeaving) + SelectAll(FALSE); + else + { + // hit test + m_aMousePos = _rEvt.maPosPixel; + Size aOutputSize = GetOutputSizePixel(); + SvLBoxEntry* pEntry = GetEntry( m_aMousePos ); + if( !pEntry ) + return DND_ACTION_NONE; + + // Scrolling Areas + Rectangle aBottomScrollArea( Point(0, aOutputSize.Height()-LISTBOX_SCROLLING_AREA), + Size(aOutputSize.Width(), LISTBOX_SCROLLING_AREA) ); + Rectangle aTopScrollArea( Point(0,0), Size(aOutputSize.Width(), LISTBOX_SCROLLING_AREA) ); + + // Wenn Zeiger auf der oberen ScrollingArea steht, nach oben scrollen + if( aBottomScrollArea.IsInside(m_aMousePos) ) + { + if( !m_aScrollTimer.IsActive() ) + { + m_aScrollTimer.SetTimeoutHdl( LINK(this, OTableWindowListBox, ScrollUpHdl) ); + ScrollUpHdl( this ); + } + } + + // Wenn Zeiger auf der oberen ScrollingArea steht, nach unten scrollen + else if( aTopScrollArea.IsInside(m_aMousePos) ) + { + if( !m_aScrollTimer.IsActive() ) + { + m_aScrollTimer.SetTimeoutHdl( LINK(this, OTableWindowListBox, ScrollDownHdl) ); + ScrollDownHdl( this ); + } + } + else + { + if( m_aScrollTimer.IsActive() ) + m_aScrollTimer.Stop(); + } + + // Beim Drag automatisch den richtigen Eintrag selektieren + if ((FirstSelected() != pEntry) || (FirstSelected() && NextSelected(FirstSelected()))) + SelectAll(FALSE); + Select(pEntry, TRUE); + + // Auf den ersten Eintrag (*) kann nicht gedroppt werden + if(!( m_pTabWin->GetData()->IsShowAll() && (pEntry==First()) )) + nDND_Action = DND_ACTION_LINK; + } + } + return nDND_Action; +} +// ----------------------------------------------------------------------------- + +//------------------------------------------------------------------------------ +IMPL_LINK( OTableWindowListBox, LookForUiHdl, void *, /*EMPTY_ARG*/) +{ + m_nUiEvent = 0; + m_pTabWin->getTableView()->lookForUiActivities(); + return 0L; +} +//------------------------------------------------------------------------------ +IMPL_LINK( OTableWindowListBox, DropHdl, void *, /*EMPTY_ARG*/) +{ + // create the connection + m_nDropEvent = 0; + OSL_ENSURE(m_pTabWin,"No TableWindow!"); + try + { + OJoinTableView* pCont = m_pTabWin->getTableView(); + OSL_ENSURE(pCont,"No QueryTableView!"); + pCont->AddConnection(m_aDropInfo.aSource, m_aDropInfo.aDest); + } + catch(const SQLException& e) + { + // remember the exception so that we can show them later when d&d is finished + m_pTabWin->getDesignView()->getController().setErrorOccurred(::dbtools::SQLExceptionInfo(e)); + } + return 0L; +} +//------------------------------------------------------------------------------ +sal_Int8 OTableWindowListBox::ExecuteDrop( const ExecuteDropEvent& _rEvt ) +{ + TransferableDataHelper aDropped(_rEvt.maDropEvent.Transferable); + if ( OJoinExchObj::isFormatAvailable(aDropped.GetDataFlavorExVector())) + { // don't drop into the window if it's the drag source itself + m_aDropInfo.aSource = OJoinExchangeData(this); + m_aDropInfo.aDest = OJoinExchObj::GetSourceDescription(_rEvt.maDropEvent.Transferable); + + if (m_nDropEvent) + Application::RemoveUserEvent(m_nDropEvent); + m_nDropEvent = Application::PostUserEvent(LINK(this, OTableWindowListBox, DropHdl)); + + return DND_ACTION_LINK; + } + return DND_ACTION_NONE; +} + +//------------------------------------------------------------------------------ +void OTableWindowListBox::LoseFocus() +{ + if(m_pTabWin) + m_pTabWin->setActive(sal_False); + SvTreeListBox::LoseFocus(); +} + +//------------------------------------------------------------------------------ +void OTableWindowListBox::GetFocus() +{ + if(m_pTabWin) + m_pTabWin->setActive(); + + if (GetCurEntry() != NULL) + { + if ( GetSelectionCount() == 0 || GetCurEntry() != FirstSelected() ) + { + if ( FirstSelected() ) + Select(FirstSelected(), FALSE); + Select(GetCurEntry(), TRUE); + } + else + ShowFocusRect(FirstSelected()); + } + SvTreeListBox::GetFocus(); +} + +//------------------------------------------------------------------------------ +IMPL_LINK( OTableWindowListBox, OnDoubleClick, SvTreeListBox *, /*pBox*/ ) +{ + // meinem Elter Bescheid sagen + Window* pParent = Window::GetParent(); + DBG_ASSERT(pParent != NULL, "OTableWindowListBox::OnDoubleClick : habe kein Parent !"); + + static_cast<OTableWindow*>(pParent)->OnEntryDoubleClicked(GetHdlEntry()); + + return 0; +} +// ----------------------------------------------------------------------------- +void OTableWindowListBox::Command(const CommandEvent& rEvt) +{ + switch (rEvt.GetCommand()) + { + case COMMAND_CONTEXTMENU: + { + static_cast<OTableWindow*>(Window::GetParent())->Command(rEvt); + break; + } + default: + SvTreeListBox::Command(rEvt); + } +} +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/TableWindowTitle.cxx b/dbaccess/source/ui/querydesign/TableWindowTitle.cxx new file mode 100644 index 000000000000..c4e9d279a03e --- /dev/null +++ b/dbaccess/source/ui/querydesign/TableWindowTitle.cxx @@ -0,0 +1,210 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "TableWindowTitle.hxx" +#include "TableWindow.hxx" +#include "QueryTableView.hxx" +#include <vcl/svapp.hxx> +#include <vcl/help.hxx> +#include <vcl/menu.hxx> +#include <tools/debug.hxx> +#include "dbustrings.hrc" +#include <sfx2/cntids.hrc> +#include "TableWindowListBox.hxx" +#include "TableConnection.hxx" +#include "dbu_qry.hrc" +#include "QueryDesignView.hxx" +#include "JoinController.hxx" + +#include <algorithm> + +using namespace dbaui; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +//================================================================== +// class OTableWindowTitle +//================================================================== +DBG_NAME(OTableWindowTitle) +//------------------------------------------------------------------------------ +OTableWindowTitle::OTableWindowTitle( OTableWindow* pParent ) : + FixedText( pParent, WB_3DLOOK|WB_LEFT|WB_NOLABEL|WB_VCENTER ) + ,m_pTabWin( pParent ) +{ + DBG_CTOR(OTableWindowTitle,NULL); + // Hintergrund- und Textfarbe setzen + StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings(); + SetBackground(Wallpaper(Color(aSystemStyle.GetFaceColor()))); + SetTextColor(aSystemStyle.GetButtonTextColor()); + + Font aFont( GetFont() ); + aFont.SetTransparent( TRUE ); + SetFont( aFont ); +} + +//------------------------------------------------------------------------------ +OTableWindowTitle::~OTableWindowTitle() +{ + DBG_DTOR(OTableWindowTitle,NULL); + m_pTabWin = NULL; +} + +//------------------------------------------------------------------------------ +void OTableWindowTitle::GetFocus() +{ + if(m_pTabWin) + m_pTabWin->GetFocus(); +} + +//------------------------------------------------------------------------------ +void OTableWindowTitle::LoseFocus() +{ + m_pTabWin->LoseFocus(); +} +//------------------------------------------------------------------------------ +void OTableWindowTitle::RequestHelp( const HelpEvent& rHEvt ) +{ + if(m_pTabWin) + { + String aHelpText = m_pTabWin->GetComposedName(); + if( aHelpText.Len()) + { + // Hilfe anzeigen + Rectangle aItemRect(Point(0,0),GetSizePixel()); + aItemRect = LogicToPixel( aItemRect ); + Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); + aItemRect.Left() = aPt.X(); + aItemRect.Top() = aPt.Y(); + aPt = OutputToScreenPixel( aItemRect.BottomRight() ); + aItemRect.Right() = aPt.X(); + aItemRect.Bottom() = aPt.Y(); + if( rHEvt.GetMode() == HELPMODE_BALLOON ) + Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aHelpText); + else + Help::ShowQuickHelp( this, aItemRect, aHelpText ); + } + } +} + +//------------------------------------------------------------------------------ +void OTableWindowTitle::Command( const CommandEvent& rEvt ) +{ + switch( rEvt.GetCommand() ) + { + case COMMAND_CONTEXTMENU: + { + GrabFocus(); + if ( m_pTabWin ) + m_pTabWin->Command( rEvt ); + else + Control::Command(rEvt); + } + } +} + +//------------------------------------------------------------------------------ +void OTableWindowTitle::KeyInput( const KeyEvent& rEvt ) +{ + if ( m_pTabWin ) + m_pTabWin->KeyInput( rEvt ); +} + +//------------------------------------------------------------------------------ +void OTableWindowTitle::MouseButtonDown( const MouseEvent& rEvt ) +{ + if( rEvt.IsLeft() ) + { + if( rEvt.GetClicks() == 2) + { + Size aSize(GetTextWidth(GetText()) + 20, + m_pTabWin->GetSizePixel().Height() - m_pTabWin->GetListBox()->GetSizePixel().Height()); + + aSize.Height() += (m_pTabWin->GetListBox()->GetEntryCount() + 2) * m_pTabWin->GetListBox()->GetEntryHeight(); + if(m_pTabWin->GetSizePixel() != aSize) + { + m_pTabWin->SetSizePixel(aSize); + + OJoinTableView* pView = static_cast<OJoinTableView*>(m_pTabWin->getTableView()); + OSL_ENSURE(pView,"No OJoinTableView!"); + const ::std::vector<OTableConnection*>* pConns = pView->getTableConnections(); + ::std::for_each(pConns->begin(), + pConns->end(), + ::std::mem_fun(&OTableConnection::RecalcLines)); + + pView->InvalidateConnections(); + pView->getDesignView()->getController().setModified(sal_True); + pView->Invalidate(INVALIDATE_NOCHILDREN); + } + } + else + { + Point aPos = rEvt.GetPosPixel(); + aPos = OutputToScreenPixel( aPos ); + OJoinTableView* pView = static_cast<OJoinTableView*>(m_pTabWin->getTableView()); + OSL_ENSURE(pView,"No OJoinTableView!"); + pView->NotifyTitleClicked( static_cast<OTableWindow*>(GetParent()), aPos ); + } + GrabFocus(); + } + else + Control::MouseButtonDown( rEvt ); +} + + +//------------------------------------------------------------------------------ +void OTableWindowTitle::DataChanged(const DataChangedEvent& rDCEvt) +{ + if (rDCEvt.GetType() == DATACHANGED_SETTINGS) + { + // nehmen wir den worst-case an : die Farben haben sich geaendert, also + // mich anpassen + StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings(); + SetBackground(Wallpaper(Color(aSystemStyle.GetFaceColor()))); + SetTextColor(aSystemStyle.GetButtonTextColor()); + } +} +// ----------------------------------------------------------------------------- +void OTableWindowTitle::StateChanged( StateChangedType nType ) +{ + Window::StateChanged( nType ); + + if ( nType == STATE_CHANGE_ZOOM ) + { + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + Font aFont = rStyleSettings.GetGroupFont(); + if ( IsControlFont() ) + aFont.Merge( GetControlFont() ); + SetZoomedPointFont( aFont ); + + Resize(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/class.jpg b/dbaccess/source/ui/querydesign/class.jpg Binary files differnew file mode 100644 index 000000000000..b1a3b6d272ad --- /dev/null +++ b/dbaccess/source/ui/querydesign/class.jpg diff --git a/dbaccess/source/ui/querydesign/makefile.mk b/dbaccess/source/ui/querydesign/makefile.mk new file mode 100644 index 000000000000..a4a39c36a79c --- /dev/null +++ b/dbaccess/source/ui/querydesign/makefile.mk @@ -0,0 +1,89 @@ +#************************************************************************* +# +# 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 +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJINC=$(PRJ)$/source +PRJNAME=dbaccess +TARGET=querydesign + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +EXCEPTIONSFILES =\ + $(SLO)$/ConnectionLine.obj \ + $(SLO)$/ConnectionLineAccess.obj \ + $(SLO)$/JAccess.obj \ + $(SLO)$/JoinController.obj \ + $(SLO)$/JoinDesignView.obj \ + $(SLO)$/JoinExchange.obj \ + $(SLO)$/JoinTableView.obj \ + $(SLO)$/QTableConnection.obj \ + $(SLO)$/QTableConnectionData.obj \ + $(SLO)$/QTableWindow.obj \ + $(SLO)$/QTableWindowData.obj \ + $(SLO)$/QueryDesignView.obj \ + $(SLO)$/QueryMoveTabWinUndoAct.obj \ + $(SLO)$/QueryTabConnUndoAction.obj \ + $(SLO)$/QueryTabWinUndoAct.obj \ + $(SLO)$/QueryTableView.obj \ + $(SLO)$/QueryTextView.obj \ + $(SLO)$/QueryViewSwitch.obj \ + $(SLO)$/SelectionBrowseBox.obj \ + $(SLO)$/TableConnection.obj \ + $(SLO)$/TableConnectionData.obj \ + $(SLO)$/TableFieldDescription.obj \ + $(SLO)$/TableWindow.obj \ + $(SLO)$/TableWindowAccess.obj \ + $(SLO)$/TableWindowData.obj \ + $(SLO)$/TableWindowListBox.obj \ + $(SLO)$/TableWindowTitle.obj \ + $(SLO)$/querycontainerwindow.obj \ + $(SLO)$/querycontroller.obj \ + $(SLO)$/querydlg.obj \ + $(SLO)$/queryview.obj + +SLOFILES =\ + $(EXCEPTIONSFILES) \ + $(SLO)$/ConnectionLineData.obj \ + $(SLO)$/TableFieldInfo.obj + +SRS1NAME=$(TARGET) +SRC1FILES = query.src \ + querydlg.src \ + +# --- Targets ------------------------------------------------------- + + +.INCLUDE : target.mk + +$(SRS)$/$(TARGET).srs: $(SOLARINCDIR)$/svx$/globlmn.hrc + + diff --git a/dbaccess/source/ui/querydesign/query.src b/dbaccess/source/ui/querydesign/query.src new file mode 100644 index 000000000000..aae5a07545ae --- /dev/null +++ b/dbaccess/source/ui/querydesign/query.src @@ -0,0 +1,426 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _DBU_QRY_HRC_ +#include "dbu_qry.hrc" +#endif +#ifndef DBAUI_QUERY_HRC +#include "Query.hrc" +#endif +#ifndef _GLOBLMN_HRC +#include <svx/globlmn.hrc> +#endif +#ifndef _CNTIDS_HRC +#include <sfx2/cntids.hrc> +#endif +#ifndef DBACCESS_UI_BROWSER_ID_HXX +#include "browserids.hxx" +#endif +#ifndef _DBA_DBACCESS_HELPID_HRC_ +#include "dbaccess_helpid.hrc" +#endif +#ifndef DBAUI_TOOLBOX_HXX +#include "toolbox.hrc" +#endif + +#define MN_EDIT 20 +#define MN_VIEW 21 +#define MN_EXTRA 22 +#define MN_INSERT 23 +#define MN_WIN 30 +#define MN_HELP 31 + +Menu RID_MENU_JOINVIEW_CONNECTION +{ + ItemList = + { + MenuItem + { + ITEM_EDIT_DELETE + }; + MenuItem + { + MID_DBUI_QUERY_EDIT_JOINCONNECTION + }; + }; +}; + +Menu RID_MENU_JOINVIEW_TABLE +{ + ItemList = + { + MenuItem + { + ITEM_EDIT_DELETE + }; + }; +}; + +Menu RID_QUERYCOLPOPUPMENU +{ + ItemList = + { + MenuItem + { + MID_COLUMN_WIDTH + }; + MenuItem + { + Separator = TRUE ; + }; + MenuItem + { + ITEM_EDIT_DELETE + }; + }; +}; + +ImageList IMG_JOINS +{ + Prefix = "jo"; + MaskColor = Color { Red = 0xffff; Green = 0x0000; Blue = 0xffff; }; + IdList = { + IMG_PRIMARY_KEY; IMG_FOREIGN_KEY; + }; + IdCount = { 2; }; +}; + +String STR_QUERY_UNDO_TABWINSHOW +{ + Text [ en-US ] = "Add Table Window" ; +}; + +String STR_QUERY_UNDO_MOVETABWIN +{ + Text [ en-US ] = "Move table window" ; +}; +String STR_QUERY_UNDO_INSERTCONNECTION +{ + Text [ en-US ] = "Insert Join" ; +}; + +String STR_QUERY_UNDO_REMOVECONNECTION +{ + Text [ en-US ] = "Delete Join" ; +}; + +String STR_QUERY_UNDO_SIZETABWIN +{ + Text [ en-US ] = "Resize table window" ; +}; +String STR_QUERY_UNDO_TABFIELDDELETE +{ + Text [ en-US ] = "Delete Column" ; +}; + +String STR_QUERY_UNDO_TABFIELDMOVED +{ + Text [ en-US ] = "Move column"; +}; + +String STR_QUERY_UNDO_TABFIELDCREATE +{ + Text [ en-US ] = "Add Column" ; +}; + +String RID_STR_TABLE_DOESNT_EXIST +{ + Text [ en-US ] = "Invalid expression, table '$name$' does not exist."; +}; + +String RID_STR_FIELD_DOESNT_EXIST +{ + Text [ en-US ] = "Invalid expression, field name '$name$' does not exist."; +}; + +String RID_STR_TOMUCHTABLES +{ + Text [ en-US ] = "The query covers #num# tables. The selected database type, however, can only process a maximum of #maxnum# table(s) per statement."; +}; + +String STR_QUERY_UNDO_TABWINDELETE +{ + Text [ en-US ] = "Delete Table Window" ; +}; + +String STR_QUERY_UNDO_MODIFY_CELL +{ + Text [ en-US ] = "Edit Column Description"; +}; + +String STR_QUERY_UNDO_SIZE_COLUMN +{ + Text [ en-US ] = "Adjust column width"; +}; + +String STR_QUERY_SORTTEXT +{ + Text [ en-US ] = "(not sorted);ascending;descending" ; +}; + +String STR_QUERY_FUNCTIONS +{ + Text [ en-US ] = "(no function);Group"; +}; + +String STR_QUERY_NOTABLE +{ + Text [ en-US ] = "(no table)"; +}; + +String STR_QRY_ORDERBY_UNRELATED +{ + Text [ en-US ] = "The database only supports sorting for visible fields."; +}; + +Menu RID_QUERYFUNCTION_POPUPMENU +{ + ItemList = + { + MenuItem + { + Identifier = ID_QUERY_FUNCTION ; + HelpID = HID_QUERY_FUNCTION; + Text [ en-US ] = "Functions"; + }; + MenuItem + { + Separator = TRUE ; + }; + MenuItem + { + Identifier = ID_QUERY_TABLENAME ; + HelpID = HID_QUERY_TABLENAME ; + Text [ en-US ] = "Table Name"; + }; + MenuItem + { + Identifier = ID_QUERY_ALIASNAME ; + HelpID = HID_QUERY_ALIASNAME ; + Text [ en-US ] = "Alias"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = ID_QUERY_DISTINCT ; + HelpID = HID_QUERY_DISTINCT ; + Text [ en-US ] = "Distinct Values"; + }; + }; +}; + +String STR_QUERY_HANDLETEXT +{ + Text [ en-US ] = "Field;Alias;Table;Sort;Visible;Function;Criterion;Or;Or"; +}; + +String STR_QRY_TOO_MANY_COLUMNS +{ + Text [ en-US ] = "There are too many columns."; +}; + +ErrorBox ERR_QRY_CRITERIA_ON_ASTERISK +{ + Message [ en-US ] = "A condition cannot be applied to field [*]" ; +}; + +String STR_QRY_TOO_LONG_STATEMENT +{ + Text [ en-US ] = "The SQL statement created is too long."; +}; + +String STR_QRY_TOOCOMPLEX +{ + Text [ en-US ] = "Query is too complex" ; +}; + +String STR_QRY_NOSELECT +{ + Text [ en-US ] = "Nothing has been selected." ; +}; + +String STR_QRY_TOOMANYCOND +{ + Text [ en-US ] = "Too many search criteria" ; +}; + +String STR_QRY_SYNTAX +{ + Text [ en-US ] = "SQL syntax error" ; +}; + +ErrorBox ERR_QRY_ORDERBY_ON_ASTERISK +{ + Message [ en-US ] = "[*] cannot be used as a sort criterion."; +}; + +String STR_QUERY_TRUE +{ + Text [ en-US ] = "TRUE" ; +}; + +String STR_QUERY_FALSE +{ + Text [ en-US ] = "FALSE" ; +}; + +String STR_QRY_TOO_MANY_TABLES +{ + Text [ en-US ] = "There are too many tables."; +}; + +String STR_QRY_NATIVE +{ + Text [ en-US ] = "The statement will not be applied when querying in the SQL dialect of the database." ; +}; + +ErrorBox ERR_QRY_AMB_FIELD +{ + Message [ en-US ] = "Field name not found or not unique" ; +}; + +String STR_QRY_ILLEGAL_JOIN +{ + Text [ en-US ] = "Join could not be processed" ; +}; + +String STR_SVT_SQL_SYNTAX_ERROR +{ + Text [ en-US ] = "Syntax error in SQL statement" ; +}; + +String STR_QUERYDESIGN_NO_VIEW_SUPPORT +{ + Text [ en-US ] = "This database does not support table views."; +}; + +String STR_NO_ALTER_VIEW_SUPPORT +{ + Text [ en-US ] = "This database does not support altering of existing table views."; +}; + +String STR_QUERYDESIGN_NO_VIEW_ASK +{ + Text [ en-US ] = "Do you want to create a query instead?"; +}; + +ErrorBox ERR_QRY_NOSTATEMENT +{ + Message [ en-US ] = "No query could be created."; +}; + +ErrorBox ERR_QRY_NOCRITERIA +{ + Message [ en-US ] = "No query could be created because no fields were selected."; +}; + +/* + The menubar resource has become obsolete - you can now find the menubar definition at: <project>/uiconfig/dbquery/menubar/menubar.xml + */ + +String STR_DATASOURCE_DELETED +{ + Text [ en-US ] = "The corresponding data source has been deleted. Therefore, data relevant to that data source cannot be saved."; +}; + +String STR_QRY_COLUMN_NOT_FOUND +{ + Text [ en-US ] = "The column '$name$' is unknown."; +}; + +String STR_QRY_JOIN_COLUMN_COMPARE +{ + Text [ en-US ] = "Columns can only be compared using '='."; +}; + +String STR_QRY_LIKE_LEFT_NO_COLUMN +{ + Text [ en-US ] = "You must use a column name before 'LIKE'."; +}; + +String STR_QRY_CHECK_CASESENSITIVE +{ + Text [ en-US ] = "The column could not be found. Please note that the database is case-sensitive."; +}; + +String STR_QUERYDESIGN +{ + Text [ en-US ] = " - %PRODUCTNAME Base: Query Design"; +}; + +String STR_VIEWDESIGN +{ + Text [ en-US ] = " - %PRODUCTNAME Base: View Design"; +}; + +String STR_QUERY_SAVEMODIFIED +{ + Text [ en-US ] = "$object$ has been changed.\nDo you want to save the changes?" ; + Text [ x-comment ] = "For $object$, one of the values of the RSC_QUERY_OBJECT_TYPE resource will be inserted."; +}; + +String STR_ERROR_PARSING_STATEMENT +{ + Text [ en-US ] = "$object$ is based on an SQL command which could not be parsed."; + Text [ x-comment ] = "For $object$, one of the values of the RSC_QUERY_OBJECT_TYPE resource " + "(except \"SQL command\", which doesn't make sense here) will be inserted."; +}; + +String STR_INFO_OPENING_IN_SQL_VIEW +{ + Text [ en-US ] = "$object$ will be opened in SQL view."; + Text [ x-comment ] = "For $object$, one of the values of the RSC_QUERY_OBJECT_TYPE resource " + "(except \"SQL command\", which doesn't make sense here) will be inserted."; +}; + +Resource RSC_QUERY_OBJECT_TYPE +{ + String 1 + { + Text [ en-US ] = "The table view"; + }; + String 2 + { + Text [ en-US ] = "The query"; + }; + String 3 + { + Text [ en-US ] = "The SQL statement"; + }; +}; + +String STR_STATEMENT_WITHOUT_RESULT_SET +{ + Text [ en-US ] = "The query does not create a result set, and thus cannot be part of another query."; +}; + +String STR_NO_DATASOURCE_OR_CONNECTION +{ + Text [ en-US ] = "Both the ActiveConnection and the DataSourceName parameter are missing or wrong - cannot initialize the query designer."; +}; diff --git a/dbaccess/source/ui/querydesign/querycontainerwindow.cxx b/dbaccess/source/ui/querydesign/querycontainerwindow.cxx new file mode 100644 index 000000000000..af5244bd281d --- /dev/null +++ b/dbaccess/source/ui/querydesign/querycontainerwindow.cxx @@ -0,0 +1,265 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "querycontainerwindow.hxx" +#include "QueryDesignView.hxx" +#include <tools/debug.hxx> +#include <vcl/svapp.hxx> +#include "JoinController.hxx" +#include <toolkit/unohlp.hxx> +#include "dbustrings.hrc" +#include <sfx2/sfxsids.hrc> +#include <vcl/fixed.hxx> +#include "UITools.hxx" +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +//......................................................................... +namespace dbaui +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::beans; + + //===================================================================== + //= OQueryContainerWindow + //===================================================================== + DBG_NAME(OQueryContainerWindow) + OQueryContainerWindow::OQueryContainerWindow(Window* pParent, OQueryController& _rController,const Reference< XMultiServiceFactory >& _rFactory) + :ODataView( pParent, _rController, _rFactory ) + ,m_pViewSwitch(NULL) + ,m_pBeamer(NULL) + { + DBG_CTOR(OQueryContainerWindow,NULL); + m_pViewSwitch = new OQueryViewSwitch( this, _rController, _rFactory ); + + m_pSplitter = new Splitter(this,WB_VSCROLL); + m_pSplitter->Hide(); + m_pSplitter->SetSplitHdl( LINK( this, OQueryContainerWindow, SplitHdl ) ); + m_pSplitter->SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetDialogColor() ) ); + } + // ----------------------------------------------------------------------------- + OQueryContainerWindow::~OQueryContainerWindow() + { + DBG_DTOR(OQueryContainerWindow,NULL); + { + ::std::auto_ptr<OQueryViewSwitch> aTemp(m_pViewSwitch); + m_pViewSwitch = NULL; + } + if ( m_pBeamer ) + ::dbaui::notifySystemWindow(this,m_pBeamer,::comphelper::mem_fun(&TaskPaneList::RemoveWindow)); + m_pBeamer = NULL; + if ( m_xBeamer.is() ) + { + Reference< ::com::sun::star::util::XCloseable > xCloseable(m_xBeamer,UNO_QUERY); + m_xBeamer = NULL; + if(xCloseable.is()) + xCloseable->close(sal_False); // false - holds the owner ship of this frame + } + + ::std::auto_ptr<Window> aTemp(m_pSplitter); + m_pSplitter = NULL; + + } + // ----------------------------------------------------------------------------- + bool OQueryContainerWindow::switchView( ::dbtools::SQLExceptionInfo* _pErrorInfo ) + { + return m_pViewSwitch->switchView( _pErrorInfo ); + } + + // ----------------------------------------------------------------------------- + void OQueryContainerWindow::forceInitialView() + { + return m_pViewSwitch->forceInitialView(); + } + + // ----------------------------------------------------------------------------- + void OQueryContainerWindow::resizeAll( const Rectangle& _rPlayground ) + { + Rectangle aPlayground( _rPlayground ); + + if ( m_pBeamer && m_pBeamer->IsVisible() ) + { + // calc pos and size of the splitter + Point aSplitPos = m_pSplitter->GetPosPixel(); + Size aSplitSize = m_pSplitter->GetOutputSizePixel(); + aSplitSize.Width() = aPlayground.GetWidth(); + + if ( aSplitPos.Y() <= aPlayground.Top() ) + aSplitPos.Y() = aPlayground.Top() + sal_Int32( aPlayground.GetHeight() * 0.2 ); + + if ( aSplitPos.Y() + aSplitSize.Height() > aPlayground.GetHeight() ) + aSplitPos.Y() = aPlayground.GetHeight() - aSplitSize.Height(); + + // set pos and size of the splitter + m_pSplitter->SetPosSizePixel( aSplitPos, aSplitSize ); + m_pSplitter->SetDragRectPixel( aPlayground ); + + // set pos and size of the beamer + Size aBeamerSize( aPlayground.GetWidth(), aSplitPos.Y() ); + m_pBeamer->SetPosSizePixel( aPlayground.TopLeft(), aBeamerSize ); + + // shrink the playground by the size which is occupied by the beamer + aPlayground.Top() = aSplitPos.Y() + aSplitSize.Height(); + } + + ODataView::resizeAll( aPlayground ); + } + + // ----------------------------------------------------------------------------- + void OQueryContainerWindow::resizeDocumentView( Rectangle& _rPlayground ) + { + m_pViewSwitch->SetPosSizePixel( _rPlayground.TopLeft(), Size( _rPlayground.GetWidth(), _rPlayground.GetHeight() ) ); + + ODataView::resizeDocumentView( _rPlayground ); + } + + // ----------------------------------------------------------------------------- + void OQueryContainerWindow::GetFocus() + { + ODataView::GetFocus(); + if(m_pViewSwitch) + m_pViewSwitch->GrabFocus(); + } + // ----------------------------------------------------------------------------- + IMPL_LINK( OQueryContainerWindow, SplitHdl, void*, /*p*/ ) + { + m_pSplitter->SetPosPixel( Point( m_pSplitter->GetPosPixel().X(),m_pSplitter->GetSplitPosPixel() ) ); + Resize(); + + return 0L; + } + + // ----------------------------------------------------------------------------- + void OQueryContainerWindow::Construct() + { + m_pViewSwitch->Construct(); + } + + // ----------------------------------------------------------------------------- + void OQueryContainerWindow::disposingPreview() + { + if ( m_pBeamer ) + { + // here I know that we will be destroyed from the frame + ::dbaui::notifySystemWindow(this,m_pBeamer,::comphelper::mem_fun(&TaskPaneList::RemoveWindow)); + m_pBeamer = NULL; + m_xBeamer = NULL; + m_pSplitter->Hide(); + Resize(); + } + } + // ----------------------------------------------------------------------------- + long OQueryContainerWindow::PreNotify( NotifyEvent& rNEvt ) + { + BOOL bHandled = FALSE; + switch (rNEvt.GetType()) + { + case EVENT_GETFOCUS: + if ( m_pViewSwitch ) + { + OJoinController& rController = m_pViewSwitch->getDesignView()->getController(); + rController.InvalidateFeature(SID_CUT); + rController.InvalidateFeature(SID_COPY); + rController.InvalidateFeature(SID_PASTE); + } + } + return bHandled ? 1L : ODataView::PreNotify(rNEvt); + } + // ----------------------------------------------------------------------------- + void OQueryContainerWindow::showPreview(const Reference<XFrame>& _xFrame) + { + if(!m_pBeamer) + { + m_pBeamer = new OBeamer(this); + + ::dbaui::notifySystemWindow(this,m_pBeamer,::comphelper::mem_fun(&TaskPaneList::AddWindow)); + + Reference < XFrame > xBeamerFrame( m_pViewSwitch->getORB()->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Frame"))),UNO_QUERY ); + m_xBeamer.set( xBeamerFrame ); + OSL_ENSURE(m_xBeamer.is(),"No frame created!"); + m_xBeamer->initialize( VCLUnoHelper::GetInterface ( m_pBeamer ) ); + + // notify layout manager to not create internal toolbars + Reference < XPropertySet > xPropSet( xBeamerFrame, UNO_QUERY ); + try + { + const ::rtl::OUString aLayoutManager( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" )); + Reference < XPropertySet > xLMPropSet(xPropSet->getPropertyValue( aLayoutManager ),UNO_QUERY); + + if ( xLMPropSet.is() ) + { + const ::rtl::OUString aAutomaticToolbars( RTL_CONSTASCII_USTRINGPARAM( "AutomaticToolbars" )); + xLMPropSet->setPropertyValue( aAutomaticToolbars, Any( sal_False )); + } + } + catch( Exception& ) + { + } + + m_xBeamer->setName(FRAME_NAME_QUERY_PREVIEW); + + // append our frame + Reference < XFramesSupplier > xSup(_xFrame,UNO_QUERY); + Reference < XFrames > xFrames = xSup->getFrames(); + xFrames->append( m_xBeamer ); + + Size aSize = GetOutputSizePixel(); + Size aBeamer(aSize.Width(),sal_Int32(aSize.Height()*0.33)); + + const long nFrameHeight = LogicToPixel( Size( 0, 3 ), MAP_APPFONT ).Height(); + Point aPos(0,aBeamer.Height()+nFrameHeight); + + m_pBeamer->SetPosSizePixel(Point(0,0),aBeamer); + m_pBeamer->Show(); + + m_pSplitter->SetPosSizePixel( Point(0,aBeamer.Height()), Size(aSize.Width(),nFrameHeight) ); + // a default pos for the splitter, so that the listbox is about 80 (logical) pixels wide + m_pSplitter->SetSplitPosPixel( aBeamer.Height() ); + m_pViewSwitch->SetPosSizePixel(aPos,Size(aBeamer.Width(),aSize.Height() - aBeamer.Height()-nFrameHeight)); + + m_pSplitter->Show(); + + Resize(); + } + } + // ----------------------------------------------------------------------------- + + +//......................................................................... +} // namespace dbaui +//......................................................................... + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/querycontroller.cxx b/dbaccess/source/ui/querydesign/querycontroller.cxx new file mode 100644 index 000000000000..cc8777a8e854 --- /dev/null +++ b/dbaccess/source/ui/querydesign/querycontroller.cxx @@ -0,0 +1,1867 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "adtabdlg.hxx" +#include "browserids.hxx" +#include "dbu_qry.hrc" +#include "dbu_reghelper.hxx" +#include "dbustrings.hrc" +#include "defaultobjectnamecheck.hxx" +#include "dlgsave.hxx" +#include "localresaccess.hxx" +#include "QTableWindow.hxx" +#include "QTableWindowData.hxx" +#include "querycontainerwindow.hxx" +#include "querycontroller.hxx" +#include "QueryDesignView.hxx" +#include "QueryTableView.hxx" +#include "QueryTextView.hxx" +#include "queryview.hxx" +#include "QueryViewSwitch.hxx" +#include "sqlmessage.hxx" +#include "TableConnectionData.hxx" +#include "TableFieldDescription.hxx" +#include "UITools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/frame/XLoadEventListener.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp> +#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp> +#include <com/sun/star/sdbc/SQLWarning.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbcx/XAppend.hpp> +#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> +#include <com/sun/star/sdbcx/XDrop.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/sdbcx/XViewsSupplier.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/util/VetoException.hpp> +#include <com/sun/star/frame/XUntitledNumbers.hpp> +/** === end UNO includes === **/ + +#include <comphelper/basicio.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/property.hxx> +#include <comphelper/seqstream.hxx> +#include <comphelper/streamsection.hxx> +#include <comphelper/types.hxx> +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <sfx2/sfxsids.hrc> +#include <svtools/localresaccess.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> +#include <osl/mutex.hxx> + +extern "C" void SAL_CALL createRegistryInfo_OQueryControl() +{ + static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::OQueryController > aAutoRegistration; +} +namespace dbaui +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::lang; + + class OViewController : public OQueryController + { + //------------------------------------------------------------------------------ + virtual ::rtl::OUString SAL_CALL getImplementationName() throw( RuntimeException ) + { + return getImplementationName_Static(); + } + //------------------------------------------------------------------------- + virtual Sequence< ::rtl::OUString> SAL_CALL getSupportedServiceNames() throw(RuntimeException) + { + return getSupportedServiceNames_Static(); + } + public: + OViewController(const Reference< XMultiServiceFactory >& _rM) : OQueryController(_rM){} + + // need by registration + static ::rtl::OUString getImplementationName_Static() throw( RuntimeException ) + { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.dbu.OViewDesign")); + } + static Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void) throw( RuntimeException ) + { + Sequence< ::rtl::OUString> aSupported(1); + aSupported.getArray()[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.ViewDesign")); + return aSupported; + } + static Reference< XInterface > SAL_CALL Create(const Reference< XMultiServiceFactory >& _rM) + { + return *(new OViewController(_rM)); + } + }; +} +extern "C" void SAL_CALL createRegistryInfo_OViewControl() +{ + static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::OViewController > aAutoRegistration; +} + +namespace dbaui +{ + using namespace ::connectivity; +#if OSL_DEBUG_LEVEL > 1 + namespace + { + // ----------------------------------------------------------------------------- + void insertParseTree(SvTreeListBox* _pBox,::connectivity::OSQLParseNode* _pNode,SvLBoxEntry* _pParent = NULL) + { + ::rtl::OUString rString; + if (!_pNode->isToken()) + { + // Regelnamen als rule: ... + rString = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RULE_ID: ")); + rString += ::rtl::OUString::valueOf( (sal_Int32)_pNode->getRuleID()); + rString+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("(")); + rString += OSQLParser::RuleIDToStr(_pNode->getRuleID()); + rString+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")")); + + + _pParent = _pBox->InsertEntry(rString,_pParent); + + // einmal auswerten wieviel Subtrees dieser Knoten besitzt + sal_uInt32 nStop = _pNode->count(); + // hol dir den ersten Subtree + for(sal_uInt32 i=0;i<nStop;++i) + insertParseTree(_pBox,_pNode->getChild(i),_pParent); + } + else + { + // ein Token gefunden + // tabs fuer das Einruecken entsprechend nLevel + + switch (_pNode->getNodeType()) + { + + case SQL_NODE_KEYWORD: + { + rString+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SQL_KEYWORD:")); + ::rtl::OString sT = OSQLParser::TokenIDToStr(_pNode->getTokenID()); + rString += ::rtl::OUString(sT,sT.getLength(),RTL_TEXTENCODING_UTF8); + break;} + + case SQL_NODE_COMPARISON: + { + rString+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SQL_COMPARISON:")); + rString += _pNode->getTokenValue(); // haenge Nodevalue an + // und beginne neu Zeile + break;} + + case SQL_NODE_NAME: + { + rString+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SQL_NAME:")); + rString+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"")); + rString += _pNode->getTokenValue(); + rString+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"")); + break;} + + case SQL_NODE_STRING: + { + rString += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SQL_STRING:'")); + rString += _pNode->getTokenValue(); + break;} + + case SQL_NODE_INTNUM: + { + rString += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SQL_INTNUM:")); + rString += _pNode->getTokenValue(); + break;} + + case SQL_NODE_APPROXNUM: + { + rString += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SQL_APPROXNUM:")); + rString += _pNode->getTokenValue(); + break;} + + case SQL_NODE_PUNCTUATION: + { + rString += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SQL_PUNCTUATION:")); + rString += _pNode->getTokenValue(); // haenge Nodevalue an + break;} + + case SQL_NODE_AMMSC: + { + rString += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SQL_AMMSC:")); + rString += _pNode->getTokenValue(); // haenge Nodevalue an + break;} + + default: + OSL_ASSERT("OSQLParser::ShowParseTree: unzulaessiger NodeType"); + rString += _pNode->getTokenValue(); + } + _pBox->InsertEntry(rString,_pParent); + } + } + } +#endif // OSL_DEBUG_LEVEL + + namespace + { + // ----------------------------------------------------------------------------- + String lcl_getObjectResourceString( USHORT _nResId, sal_Int32 _nCommandType ) + { + String sMessageText = String( ModuleRes( _nResId ) ); + String sObjectType; + { + LocalResourceAccess aLocalRes( RSC_QUERY_OBJECT_TYPE, RSC_RESOURCE ); + sObjectType = String( ModuleRes( (USHORT)( _nCommandType + 1 ) ) ); + } + sMessageText.SearchAndReplace( String::CreateFromAscii( "$object$" ), sObjectType ); + return sMessageText; + } + } + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::awt; +using namespace ::dbtools; + +using namespace ::comphelper; + +namespace +{ + void ensureToolbars( OQueryController& _rController, sal_Bool _bDesign ) + { + Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager = _rController.getLayoutManager( _rController.getFrame() ); + if ( xLayoutManager.is() ) + { + xLayoutManager->lock(); + static ::rtl::OUString s_sDesignToolbar(RTL_CONSTASCII_USTRINGPARAM("private:resource/toolbar/designobjectbar")); + static ::rtl::OUString s_sSqlToolbar(RTL_CONSTASCII_USTRINGPARAM("private:resource/toolbar/sqlobjectbar")); + if ( _bDesign ) + { + xLayoutManager->destroyElement( s_sSqlToolbar ); + xLayoutManager->createElement( s_sDesignToolbar ); + } + else + { + xLayoutManager->destroyElement( s_sDesignToolbar ); + xLayoutManager->createElement( s_sSqlToolbar ); + } + xLayoutManager->unlock(); + xLayoutManager->doLayout(); + } + } +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OQueryController::getImplementationName() throw( RuntimeException ) +{ + return getImplementationName_Static(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString OQueryController::getImplementationName_Static() throw( RuntimeException ) +{ + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.dbu.OQueryDesign")); +} +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString> OQueryController::getSupportedServiceNames_Static(void) throw( RuntimeException ) +{ + Sequence< ::rtl::OUString> aSupported(1); + aSupported.getArray()[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.QueryDesign")); + return aSupported; +} +//------------------------------------------------------------------------- +Sequence< ::rtl::OUString> SAL_CALL OQueryController::getSupportedServiceNames() throw(RuntimeException) +{ + return getSupportedServiceNames_Static(); +} +// ------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OQueryController::Create(const Reference<XMultiServiceFactory >& _rxFactory) +{ + return *(new OQueryController(_rxFactory)); +} +DBG_NAME(OQueryController); +// ----------------------------------------------------------------------------- +OQueryController::OQueryController(const Reference< XMultiServiceFactory >& _rM) + :OJoinController(_rM) + ,OQueryController_PBase( getBroadcastHelper() ) + ,m_pParseContext( new svxform::OSystemParseContext ) + ,m_aSqlParser( _rM, m_pParseContext ) + ,m_pSqlIterator(NULL) + ,m_nVisibleRows(0x400) + ,m_nSplitPos(-1) + ,m_nCommandType( CommandType::QUERY ) + ,m_bGraphicalDesign(sal_False) + ,m_bDistinct(sal_False) + ,m_bViewAlias(sal_False) + ,m_bViewTable(sal_False) + ,m_bViewFunction(sal_False) + ,m_bEscapeProcessing(sal_True) +{ + DBG_CTOR(OQueryController,NULL); + InvalidateAll(); + + registerProperty( PROPERTY_ACTIVECOMMAND, PROPERTY_ID_ACTIVECOMMAND, PropertyAttribute::READONLY | PropertyAttribute::BOUND, + &m_sStatement, ::getCppuType( &m_sStatement ) ); + registerProperty( PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::READONLY | PropertyAttribute::BOUND, + &m_bEscapeProcessing, ::getCppuType( &m_bEscapeProcessing ) ); +} + +// ----------------------------------------------------------------------------- +OQueryController::~OQueryController() +{ + DBG_DTOR(OQueryController,NULL); + if ( !getBroadcastHelper().bDisposed && !getBroadcastHelper().bInDispose ) + { + OSL_ENSURE(0,"Please check who doesn't dispose this component!"); + // increment ref count to prevent double call of Dtor + osl_incrementInterlockedCount( &m_refCount ); + dispose(); + } +} + +IMPLEMENT_FORWARD_XINTERFACE2( OQueryController, OJoinController, OQueryController_PBase ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( OQueryController, OJoinController, OQueryController_PBase ) + +//------------------------------------------------------------------------- +Reference< XPropertySetInfo > SAL_CALL OQueryController::getPropertySetInfo() throw(RuntimeException) +{ + Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + return xInfo; +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL OQueryController::convertFastPropertyValue( Any& o_rConvertedValue, Any& o_rOldValue, sal_Int32 i_nHandle, const Any& i_rValue ) throw (IllegalArgumentException) +{ + return OPropertyContainer::convertFastPropertyValue( o_rConvertedValue, o_rOldValue, i_nHandle, i_rValue ); +} + +//------------------------------------------------------------------------- +void SAL_CALL OQueryController::setFastPropertyValue_NoBroadcast( sal_Int32 i_nHandle, const Any& i_rValue ) throw ( Exception ) +{ + OPropertyContainer::setFastPropertyValue_NoBroadcast( i_nHandle, i_rValue ); +} + +//------------------------------------------------------------------------- +void SAL_CALL OQueryController::getFastPropertyValue( Any& o_rValue, sal_Int32 i_nHandle ) const +{ + switch ( i_nHandle ) + { + case PROPERTY_ID_CURRENT_QUERY_DESIGN: + { + ::comphelper::NamedValueCollection aCurrentDesign; + aCurrentDesign.put( "GraphicalDesign", isGraphicalDesign() ); + aCurrentDesign.put( (::rtl::OUString)PROPERTY_ESCAPE_PROCESSING, m_bEscapeProcessing ); + + if ( isGraphicalDesign() ) + { + getContainer()->SaveUIConfig(); + saveViewSettings( aCurrentDesign, true ); + aCurrentDesign.put( "Statement", m_sStatement ); + } + else + { + aCurrentDesign.put( "Statement", getContainer()->getStatement() ); + } + + o_rValue <<= aCurrentDesign.getPropertyValues(); + } + break; + + default: + OPropertyContainer::getFastPropertyValue( o_rValue, i_nHandle ); + break; + } +} + +//------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper& OQueryController::getInfoHelper() +{ + return *const_cast< OQueryController* >( this )->getArrayHelper(); +} + +//-------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* OQueryController::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties( aProps ); + + // one additional property: + const sal_Int32 nLength = aProps.getLength(); + aProps.realloc( nLength + 1 ); + aProps[ nLength ] = Property( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CurrentQueryDesign" ) ), + PROPERTY_ID_CURRENT_QUERY_DESIGN, + ::cppu::UnoType< Sequence< PropertyValue > >::get(), + PropertyAttribute::READONLY + ); + + ::std::sort( + aProps.getArray(), + aProps.getArray() + aProps.getLength(), + ::comphelper::PropertyCompareByName() + ); + + return new ::cppu::OPropertyArrayHelper(aProps); +} + +// ----------------------------------------------------------------------------- +void OQueryController::deleteIterator() +{ + if(m_pSqlIterator) + { + delete m_pSqlIterator->getParseTree(); + m_pSqlIterator->dispose(); + delete m_pSqlIterator; + m_pSqlIterator = NULL; + } +} +// ----------------------------------------------------------------------------- +void OQueryController::disposing() +{ + OQueryController_PBase::disposing(); + + deleteIterator(); + + delete m_pParseContext; + + clearFields(); + OTableFields().swap(m_vUnUsedFieldsDesc); + + ::comphelper::disposeComponent(m_xComposer); + OJoinController::disposing(); + OQueryController_PBase::disposing(); +} +// ----------------------------------------------------------------------------- +void OQueryController::clearFields() +{ + OTableFields().swap(m_vTableFieldDesc); +} +// ----------------------------------------------------------------------------- +FeatureState OQueryController::GetState(sal_uInt16 _nId) const +{ + FeatureState aReturn; + aReturn.bEnabled = sal_True; + // (disabled automatically) + + switch (_nId) + { + case ID_BROWSER_EDITDOC: + if ( editingCommand() ) + aReturn.bEnabled = sal_False; + else if ( editingView() && !m_xAlterView.is() ) + aReturn.bEnabled = sal_False; + else + aReturn = OJoinController::GetState( _nId ); + break; + + case ID_BROWSER_ESACPEPROCESSING: + aReturn.bChecked = !m_bEscapeProcessing; + aReturn.bEnabled = ( m_pSqlIterator != NULL ) && !m_bGraphicalDesign; + break; + case SID_RELATION_ADD_RELATION: + aReturn.bEnabled = isEditable() && m_bGraphicalDesign && m_vTableData.size() > 1; + break; + case ID_BROWSER_SAVEASDOC: + aReturn.bEnabled = !editingCommand() && !editingView() && (!m_bGraphicalDesign || !(m_vTableFieldDesc.empty() || m_vTableData.empty())); + break; + case ID_BROWSER_SAVEDOC: + aReturn.bEnabled = impl_isModified() && (!m_bGraphicalDesign || !(m_vTableFieldDesc.empty() || m_vTableData.empty())); + break; + case SID_PRINTDOCDIRECT: + break; + case ID_BROWSER_CUT: + aReturn.bEnabled = isEditable() && getContainer() && getContainer()->isCutAllowed(); + break; + case ID_BROWSER_COPY: + aReturn.bEnabled = getContainer() && getContainer()->isCopyAllowed(); + break; + case ID_BROWSER_PASTE: + aReturn.bEnabled = isEditable() && getContainer() && getContainer()->isPasteAllowed(); + break; + case ID_BROWSER_SQL: + aReturn.bEnabled = m_bEscapeProcessing && m_pSqlIterator; + aReturn.bChecked = m_bGraphicalDesign; + break; + case SID_BROWSER_CLEAR_QUERY: + aReturn.bEnabled = isEditable() && (m_sStatement.getLength() || !m_vTableData.empty()); + break; + case SID_QUERY_VIEW_FUNCTIONS: + case SID_QUERY_VIEW_TABLES: + case SID_QUERY_VIEW_ALIASES: + aReturn.bChecked = getContainer() && getContainer()->isSlotEnabled(_nId); + aReturn.bEnabled = m_bGraphicalDesign; + break; + case SID_QUERY_DISTINCT_VALUES: + aReturn.bEnabled = m_bGraphicalDesign && isEditable(); + aReturn.bChecked = m_bDistinct; + break; + case ID_BROWSER_QUERY_EXECUTE: + aReturn.bEnabled = sal_True; + break; + case SID_DB_QUERY_PREVIEW: + aReturn.bEnabled = sal_True; + aReturn.bChecked = getContainer() && getContainer()->getPreviewFrame().is(); + break; +#if OSL_DEBUG_LEVEL > 1 + case ID_EDIT_QUERY_SQL: + break; + case ID_EDIT_QUERY_DESIGN: + break; +#endif + case ID_BROWSER_ADDTABLE: + if ( !m_bGraphicalDesign ) + { + aReturn.bEnabled = sal_False; + break; + } + // run through + default: + aReturn = OJoinController::GetState(_nId); + break; + } + return aReturn; +} +// ----------------------------------------------------------------------------- +void OQueryController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs) +{ + switch(_nId) + { + case ID_BROWSER_ESACPEPROCESSING: + setEscapeProcessing_fireEvent( !m_bEscapeProcessing ); + if ( !editingView() ) + setModified(sal_True); + InvalidateFeature(ID_BROWSER_SQL); + break; + case ID_BROWSER_SAVEASDOC: + case ID_BROWSER_SAVEDOC: + doSaveAsDoc(ID_BROWSER_SAVEASDOC == _nId); + break; + case SID_RELATION_ADD_RELATION: + { + OJoinDesignView* pView = getJoinView(); + if( pView ) + static_cast<OQueryTableView*>(pView->getTableView())->createNewConnection(); + } + break; + case SID_PRINTDOCDIRECT: + break; + case ID_BROWSER_CUT: + getContainer()->cut(); + break; + case ID_BROWSER_COPY: + getContainer()->copy(); + break; + case ID_BROWSER_PASTE: + getContainer()->paste(); + break; + case ID_BROWSER_SQL: + { + if ( !getContainer()->checkStatement() ) + break; + SQLExceptionInfo aError; + try + { + ::rtl::OUString aErrorMsg; + setStatement_fireEvent( getContainer()->getStatement() ); + if(!m_sStatement.getLength() && m_pSqlIterator) + { + // change the view of the data + delete m_pSqlIterator->getParseTree(); + m_pSqlIterator->setParseTree(NULL); + m_bGraphicalDesign = !m_bGraphicalDesign; + impl_setViewMode( &aError ); + } + else + { + ::connectivity::OSQLParseNode* pNode = m_aSqlParser.parseTree(aErrorMsg,m_sStatement,m_bGraphicalDesign); + if ( pNode ) + { + delete m_pSqlIterator->getParseTree(); + m_pSqlIterator->setParseTree(pNode); + m_pSqlIterator->traverseAll(); + + if ( m_pSqlIterator->hasErrors() ) + { + aError = m_pSqlIterator->getErrors(); + } + else + { + const OSQLTables& xTabs = m_pSqlIterator->getTables(); + if ( m_pSqlIterator->getStatementType() != SQL_STATEMENT_SELECT || xTabs.begin() == xTabs.end() ) + { + aError = SQLException( + String( ModuleRes( STR_QRY_NOSELECT ) ), + NULL, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "S1000" ) ), + 1000, + Any() + ); + } + else + { + // change the view of the data + m_bGraphicalDesign = !m_bGraphicalDesign; + ::rtl::OUString sNewStatement; + pNode->parseNodeToStr( sNewStatement, getConnection() ); + setStatement_fireEvent( sNewStatement ); + getContainer()->SaveUIConfig(); + m_vTableConnectionData.clear(); + impl_setViewMode( &aError ); + } + } + } + else + { + aError = SQLException( + String( ModuleRes( STR_QRY_SYNTAX ) ), + NULL, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "S1000" ) ), + 1000, + Any() + ); + } + } + } + catch(const SQLException& e) + { + aError = ::cppu::getCaughtException(); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if ( aError.isValid() ) + showError( aError ); + + if(m_bGraphicalDesign) + { + InvalidateFeature(ID_BROWSER_ADDTABLE); + InvalidateFeature(SID_RELATION_ADD_RELATION); + } + } + break; + case SID_BROWSER_CLEAR_QUERY: + { + getUndoMgr()->EnterListAction( String( ModuleRes(STR_QUERY_UNDO_TABWINDELETE) ), String() ); + getContainer()->clear(); + getUndoMgr()->LeaveListAction(); + + setStatement_fireEvent( ::rtl::OUString() ); + if(m_bGraphicalDesign) + InvalidateFeature(ID_BROWSER_ADDTABLE); + } + break; + case SID_QUERY_VIEW_FUNCTIONS: + case SID_QUERY_VIEW_TABLES: + case SID_QUERY_VIEW_ALIASES: + getContainer()->setSlotEnabled(_nId,!getContainer()->isSlotEnabled(_nId)); + setModified(sal_True); + break; + case SID_QUERY_DISTINCT_VALUES: + m_bDistinct = !m_bDistinct; + setModified(sal_True); + break; + case ID_BROWSER_QUERY_EXECUTE: + if ( getContainer()->checkStatement() ) + executeQuery(); + break; + case SID_DB_QUERY_PREVIEW: + try + { + Reference< ::com::sun::star::util::XCloseable > xCloseFrame( getContainer()->getPreviewFrame(), UNO_QUERY ); + if ( xCloseFrame.is() ) + { + try + { + xCloseFrame->close( sal_True ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OQueryController::Execute(SID_DB_QUERY_PREVIEW): *nobody* is expected to veto closing the preview frame!" ); + } + } + else + Execute(ID_BROWSER_QUERY_EXECUTE,Sequence< PropertyValue >()); + } + catch(Exception&) + { + } + break; + case ID_QUERY_ZOOM_IN: + { + } + break; + case ID_QUERY_ZOOM_OUT: + { + } + break; +#if OSL_DEBUG_LEVEL > 1 + case ID_EDIT_QUERY_DESIGN: + case ID_EDIT_QUERY_SQL: + { + ::rtl::OUString aErrorMsg; + setStatement_fireEvent( getContainer()->getStatement() ); + ::connectivity::OSQLParseNode* pNode = m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign ); + if ( pNode ) + { + Window* pView = getView(); + ModalDialog* pWindow = new ModalDialog( pView, WB_STDMODAL | WB_SIZEMOVE | WB_CENTER ); + pWindow->SetSizePixel( ::Size( pView->GetSizePixel().Width() / 2, pView->GetSizePixel().Height() / 2 ) ); + SvTreeListBox* pTreeBox = new SvTreeListBox( pWindow, WB_BORDER | WB_HASLINES | WB_HASBUTTONS | WB_HASBUTTONSATROOT | WB_HASLINESATROOT | WB_VSCROLL ); + pTreeBox->SetPosSizePixel( ::Point( 6, 6 ), ::Size( pWindow->GetSizePixel().Width() - 12, pWindow->GetSizePixel().Height() - 12 )); + pTreeBox->SetNodeDefaultImages(); + + if ( _nId == ID_EDIT_QUERY_DESIGN ) + { + ::connectivity::OSQLParseNode* pTemp = pNode ? pNode->getChild(3)->getChild(1) : NULL; + // no where clause found + if ( pTemp && !pTemp->isLeaf() ) + { + ::connectivity::OSQLParseNode * pCondition = pTemp->getChild(1); + if ( pCondition ) // no where clause + { + ::connectivity::OSQLParseNode::negateSearchCondition(pCondition); + ::connectivity::OSQLParseNode *pNodeTmp = pTemp->getChild(1); + + ::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp); + pNodeTmp = pTemp->getChild(1); + ::connectivity::OSQLParseNode::absorptions(pNodeTmp); + pNodeTmp = pTemp->getChild(1); + OSQLParseNode::compress(pNodeTmp); + pNodeTmp = pTemp->getChild(1); + } + ::rtl::OUString sTemp; + pNode->parseNodeToStr(sTemp,getConnection()); + getContainer()->setStatement(sTemp); + } + } + + insertParseTree(pTreeBox,pNode); + + pTreeBox->Show(); + pWindow->Execute(); + + delete pTreeBox; + delete pWindow; + delete pNode; + } + break; + } +#endif + default: + OJoinController::Execute(_nId,aArgs); + return; // else we would invalidate twice + } + InvalidateFeature(_nId); +} + +// ----------------------------------------------------------------------------- +void OQueryController::impl_showAutoSQLViewError( const ::com::sun::star::uno::Any& _rErrorDetails ) +{ + SQLContext aErrorContext; + aErrorContext.Message = lcl_getObjectResourceString( STR_ERROR_PARSING_STATEMENT, m_nCommandType ); + aErrorContext.Context = *this; + aErrorContext.Details = lcl_getObjectResourceString( STR_INFO_OPENING_IN_SQL_VIEW, m_nCommandType ); + aErrorContext.NextException = _rErrorDetails; + showError( aErrorContext ); +} + +// ----------------------------------------------------------------------------- +bool OQueryController::impl_setViewMode( ::dbtools::SQLExceptionInfo* _pErrorInfo ) +{ + OSL_PRECOND( getContainer(), "OQueryController::impl_setViewMode: illegal call!" ); + + bool wasModified = isModified(); + + SQLExceptionInfo aError; + bool bSuccess = getContainer()->switchView( &aError ); + if ( !bSuccess ) + { + m_bGraphicalDesign = !m_bGraphicalDesign; + // restore old state + getContainer()->switchView( NULL ); + // don't pass &aError here, this would overwrite the error which the first switchView call + // returned in this location. + if ( _pErrorInfo ) + *_pErrorInfo = aError; + else + showError( aError ); + } + else + { + ensureToolbars( *this, m_bGraphicalDesign ); + } + + setModified( wasModified ); + return bSuccess; +} + +// ----------------------------------------------------------------------------- +void OQueryController::impl_initialize() +{ + OJoinController::impl_initialize(); + + const NamedValueCollection& rArguments( getInitParams() ); + + ::rtl::OUString sCommand; + m_nCommandType = CommandType::QUERY; + + // °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + // ° reading parameters + // °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + // legacy parameters first (later overwritten by regular parameters) + ::rtl::OUString sIndependentSQLCommand; + if ( rArguments.get_ensureType( "IndependentSQLCommand", sIndependentSQLCommand ) ) + { + OSL_ENSURE( false, "OQueryController::impl_initialize: IndependentSQLCommand is regognized for compatibility only!" ); + sCommand = sIndependentSQLCommand; + m_nCommandType = CommandType::COMMAND; + } + + ::rtl::OUString sCurrentQuery; + if ( rArguments.get_ensureType( "CurrentQuery", sCurrentQuery ) ) + { + OSL_ENSURE( false, "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" ); + sCommand = sCurrentQuery; + m_nCommandType = CommandType::QUERY; + } + + sal_Bool bCreateView( sal_False ); + if ( rArguments.get_ensureType( "CreateView", bCreateView ) && bCreateView ) + { + OSL_ENSURE( false, "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" ); + m_nCommandType = CommandType::TABLE; + } + + // non-legacy parameters which overwrite the legacy parameters + rArguments.get_ensureType( (::rtl::OUString)PROPERTY_COMMAND, sCommand ); + rArguments.get_ensureType( (::rtl::OUString)PROPERTY_COMMAND_TYPE, m_nCommandType ); + + // translate Command/Type into proper members + // TODO/Later: all this (including those members) should be hidden behind some abstact interface, + // which is implemented for all the three commands + switch ( m_nCommandType ) + { + case CommandType::QUERY: + m_sName = sCommand; + break; + case CommandType::TABLE: + m_sName = sCommand; + break; + case CommandType::COMMAND: + setStatement_fireEvent( sCommand ); + m_sName = ::rtl::OUString(); + break; + default: + OSL_ENSURE( false, "OQueryController::impl_initialize: logic error in code!" ); + throw RuntimeException(); + } + + // more legacy parameters + sal_Bool bGraphicalDesign( sal_True ); + if ( rArguments.get_ensureType( (::rtl::OUString)PROPERTY_QUERYDESIGNVIEW, bGraphicalDesign ) ) + { + OSL_ENSURE( false, "OQueryController::impl_initialize: QueryDesignView is regognized for compatibility only!" ); + m_bGraphicalDesign = bGraphicalDesign; + } + + // more non-legacy + rArguments.get_ensureType( (::rtl::OUString)PROPERTY_GRAPHICAL_DESIGN, m_bGraphicalDesign ); + + bool bEscapeProcessing( sal_True ); + if ( rArguments.get_ensureType( (::rtl::OUString)PROPERTY_ESCAPE_PROCESSING, bEscapeProcessing ) ) + { + setEscapeProcessing_fireEvent( bEscapeProcessing ); + + OSL_ENSURE( m_bEscapeProcessing || !m_bGraphicalDesign, "OQueryController::impl_initialize: can't do the graphical design without escape processing!" ); + if ( !m_bEscapeProcessing ) + m_bGraphicalDesign = false; + } + + // ................................................................................................................. + // . initial design + bool bForceInitialDesign = false; + Sequence< PropertyValue > aCurrentQueryDesignProps; + aCurrentQueryDesignProps = rArguments.getOrDefault( "CurrentQueryDesign", aCurrentQueryDesignProps ); + + if ( aCurrentQueryDesignProps.getLength() ) + { + ::comphelper::NamedValueCollection aCurrentQueryDesign( aCurrentQueryDesignProps ); + if ( aCurrentQueryDesign.has( (::rtl::OUString)PROPERTY_GRAPHICAL_DESIGN ) ) + { + aCurrentQueryDesign.get_ensureType( (::rtl::OUString)PROPERTY_GRAPHICAL_DESIGN, m_bGraphicalDesign ); + } + if ( aCurrentQueryDesign.has( (::rtl::OUString)PROPERTY_ESCAPE_PROCESSING ) ) + { + aCurrentQueryDesign.get_ensureType( (::rtl::OUString)PROPERTY_ESCAPE_PROCESSING, m_bEscapeProcessing ); + } + if ( aCurrentQueryDesign.has( "Statement" ) ) + { + ::rtl::OUString sStatement; + aCurrentQueryDesign.get_ensureType( "Statement", sStatement ); + aCurrentQueryDesign.remove( "Statement" ); + setStatement_fireEvent( sStatement ); + } + + loadViewSettings( aCurrentQueryDesign ); + + bForceInitialDesign = true; + } + + // °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + if ( !ensureConnected( sal_False ) ) + { // we have no connection so what else should we do + m_bGraphicalDesign = sal_False; + if ( editingView() ) + { + connectionLostMessage(); + throw SQLException(); + } + } + + // check the view capabilities + if ( isConnected() && editingView() ) + { + Reference< XViewsSupplier > xViewsSup( getConnection(), UNO_QUERY ); + Reference< XNameAccess > xViews; + if ( xViewsSup.is() ) + xViews = xViewsSup->getViews(); + + if ( !xViews.is() ) + { // we can't create views so we ask if the user wants to create a query instead + m_nCommandType = CommandType::QUERY; + sal_Bool bClose = sal_False; + { + String aTitle( ModuleRes( STR_QUERYDESIGN_NO_VIEW_SUPPORT ) ); + String aMessage( ModuleRes( STR_QUERYDESIGN_NO_VIEW_ASK ) ); + ODataView* pWindow = getView(); + OSQLMessageBox aDlg( pWindow, aTitle, aMessage, WB_YES_NO | WB_DEF_YES, OSQLMessageBox::Query ); + bClose = aDlg.Execute() == RET_NO; + } + if ( bClose ) + throw VetoException(); + } + + // now if we are to edit an existing view, check whether this is possible + if ( m_sName.getLength() ) + { + Any aView( xViews->getByName( m_sName ) ); + // will throw if there is no such view + if ( !( aView >>= m_xAlterView ) ) + { + throw IllegalArgumentException( + ::rtl::OUString( String( ModuleRes( STR_NO_ALTER_VIEW_SUPPORT ) ) ), + *this, + 1 + ); + } + } + } + + OSL_ENSURE(getDataSource().is(),"OQueryController::impl_initialize: need a datasource!"); + + try + { + getContainer()->initialize(); + impl_reset( bForceInitialDesign ); + + SQLExceptionInfo aError; + const bool bAttemptedGraphicalDesign = m_bGraphicalDesign; + + if ( bForceInitialDesign ) + { + getContainer()->forceInitialView(); + } + else + { + impl_setViewMode( &aError ); + } + + if ( aError.isValid() && bAttemptedGraphicalDesign && !m_bGraphicalDesign ) + { + // we tried initializing the graphical view, this failed, and we were automatically switched to SQL + // view => tell this to the user + if ( !editingView() ) + { + impl_showAutoSQLViewError( aError.get() ); + } + } + + getUndoMgr()->Clear(); + + if ( ( m_bGraphicalDesign ) + && ( ( !m_sName.getLength() && !editingCommand() ) + || ( !m_sStatement.getLength() && editingCommand() ) + ) + ) + { + Application::PostUserEvent( LINK( this, OQueryController, OnExecuteAddTable ) ); + } + + setModified(sal_False); + } + catch(SQLException& e) + { + DBG_UNHANDLED_EXCEPTION(); + // we caught an exception so we switch to text only mode + { + m_bGraphicalDesign = sal_False; + getContainer()->initialize(); + ODataView* pWindow = getView(); + OSQLMessageBox(pWindow,e).Execute(); + } + throw; + } +} + +// ----------------------------------------------------------------------------- +void OQueryController::onLoadedMenu(const Reference< ::com::sun::star::frame::XLayoutManager >& /*_xLayoutManager*/) +{ + ensureToolbars( *this, m_bGraphicalDesign ); +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OQueryController::getPrivateTitle( ) const +{ + ::rtl::OUString sName = m_sName; + if ( !sName.getLength() ) + { + if ( !editingCommand() ) + { + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( getMutex() ); + String aDefaultName = String( ModuleRes( editingView() ? STR_VIEW_TITLE : STR_QRY_TITLE ) ); + sName = aDefaultName.GetToken(0,' '); + sName += ::rtl::OUString::valueOf(getCurrentStartNumber()); + } + } + return sName; +} +// ----------------------------------------------------------------------------- +void OQueryController::setQueryComposer() +{ + if(isConnected()) + { + Reference< XSQLQueryComposerFactory > xFactory(getConnection(), UNO_QUERY); + OSL_ENSURE(xFactory.is(),"Connection doesn't support a querycomposer"); + if ( xFactory.is() && getContainer() ) + { + try + { + m_xComposer = xFactory->createQueryComposer(); + getContainer()->setStatement(m_sStatement); + } + catch (Exception&) + { + m_xComposer = NULL; + } + OSL_ENSURE(m_xComposer.is(),"No querycomposer available!"); + Reference<XTablesSupplier> xTablesSup(getConnection(), UNO_QUERY); + deleteIterator(); + m_pSqlIterator = new ::connectivity::OSQLParseTreeIterator( getConnection(), xTablesSup->getTables(), m_aSqlParser, NULL ); + } + } +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryController::Construct(Window* pParent) +{ + // TODO: we have to check if we should create the text- or the design- view + + setView( * new OQueryContainerWindow( pParent, *this, getORB() ) ); + + return OJoinController::Construct(pParent); +} + +// ----------------------------------------------------------------------------- +OJoinDesignView* OQueryController::getJoinView() +{ + return getContainer()->getDesignView(); +} +// ----------------------------------------------------------------------------- +void OQueryController::describeSupportedFeatures() +{ + OJoinController::describeSupportedFeatures(); + implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC, CommandGroup::DOCUMENT ); + implDescribeSupportedFeature( ".uno:SbaNativeSql", ID_BROWSER_ESACPEPROCESSING,CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DBViewFunctions", SID_QUERY_VIEW_FUNCTIONS, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:DBViewTableNames", SID_QUERY_VIEW_TABLES, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:DBViewAliases", SID_QUERY_VIEW_ALIASES, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:DBDistinctValues", SID_QUERY_DISTINCT_VALUES, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DBChangeDesignMode",ID_BROWSER_SQL, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:DBClearQuery", SID_BROWSER_CLEAR_QUERY, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:SbaExecuteSql", ID_BROWSER_QUERY_EXECUTE, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:DBAddRelation", SID_RELATION_ADD_RELATION, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:DBQueryPreview", SID_DB_QUERY_PREVIEW, CommandGroup::VIEW ); + +#if OSL_DEBUG_LEVEL > 1 + implDescribeSupportedFeature( ".uno:DBShowParseTree", ID_EDIT_QUERY_SQL ); + implDescribeSupportedFeature( ".uno:DBMakeDisjunct", ID_EDIT_QUERY_DESIGN ); +#endif +} +// ----------------------------------------------------------------------------- +void OQueryController::impl_onModifyChanged() +{ + OJoinController::impl_onModifyChanged(); + InvalidateFeature(SID_BROWSER_CLEAR_QUERY); + InvalidateFeature(ID_BROWSER_SAVEASDOC); + InvalidateFeature(ID_BROWSER_QUERY_EXECUTE); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQueryController::disposing( const EventObject& Source ) throw(RuntimeException) +{ + SolarMutexGuard aGuard; + + if ( getContainer() && Source.Source.is() ) + { + if ( Source.Source == m_aCurrentFrame.getFrame() ) + { // our frame is being disposed -> close the preview window (if we have one) + Reference< XFrame > xPreviewFrame( getContainer()->getPreviewFrame() ); + ::comphelper::disposeComponent( xPreviewFrame ); + } + else if ( Source.Source == getContainer()->getPreviewFrame() ) + { + getContainer()->disposingPreview(); + } + } + + OJoinController::disposing(Source); +} +// ----------------------------------------------------------------------------- +void OQueryController::reconnect(sal_Bool _bUI) +{ + deleteIterator(); + ::comphelper::disposeComponent(m_xComposer); + + OJoinController::reconnect( _bUI ); + + if (isConnected()) + { + setQueryComposer(); + } + else + { + if(m_bGraphicalDesign) + { + m_bGraphicalDesign = sal_False; + // don't call Execute(SQL) because this changes the sql statement + impl_setViewMode( NULL ); + } + InvalidateAll(); + } +} + +// ----------------------------------------------------------------------------- +void OQueryController::saveViewSettings( ::comphelper::NamedValueCollection& o_rViewSettings, const bool i_includingCriteria ) const +{ + saveTableWindows( o_rViewSettings ); + + OTableFields::const_iterator field = m_vTableFieldDesc.begin(); + OTableFields::const_iterator fieldEnd = m_vTableFieldDesc.end(); + + ::comphelper::NamedValueCollection aAllFieldsData; + ::comphelper::NamedValueCollection aFieldData; + for ( sal_Int32 i = 1; field != fieldEnd; ++field, ++i ) + { + if ( !(*field)->IsEmpty() ) + { + aFieldData.clear(); + (*field)->Save( aFieldData, i_includingCriteria ); + + const ::rtl::OUString sFieldSettingName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Field" ) ) + ::rtl::OUString::valueOf( i ); + aAllFieldsData.put( sFieldSettingName, aFieldData.getPropertyValues() ); + } + } + + o_rViewSettings.put( "Fields", aAllFieldsData.getPropertyValues() ); + o_rViewSettings.put( "SplitterPosition", m_nSplitPos ); + o_rViewSettings.put( "VisibleRows", m_nVisibleRows ); +} +// ----------------------------------------------------------------------------- +void OQueryController::loadViewSettings( const ::comphelper::NamedValueCollection& o_rViewSettings ) +{ + loadTableWindows( o_rViewSettings ); + + m_nSplitPos = o_rViewSettings.getOrDefault( "SplitterPosition", m_nSplitPos ); + m_nVisibleRows = o_rViewSettings.getOrDefault( "VisibleRows", m_nVisibleRows ); + m_aFieldInformation = o_rViewSettings.getOrDefault( "Fields", m_aFieldInformation ); +} +// ----------------------------------------------------------------------------- +sal_Int32 OQueryController::getColWidth(sal_uInt16 _nColPos) const +{ + if ( _nColPos < m_aFieldInformation.getLength() ) + { + ::std::auto_ptr<OTableFieldDesc> pField( new OTableFieldDesc()); + pField->Load( m_aFieldInformation[ _nColPos ], false ); + return pField->GetColWidth(); + } + return 0; +} +// ----------------------------------------------------------------------------- +Reference<XNameAccess> OQueryController::getObjectContainer() const +{ + Reference< XNameAccess > xElements; + if ( editingView() ) + { + Reference< XViewsSupplier > xViewsSupp( getConnection(), UNO_QUERY ); + if ( xViewsSupp.is() ) + xElements = xViewsSupp->getViews(); + } + else + { + Reference< XQueriesSupplier > xQueriesSupp( getConnection(), UNO_QUERY ); + if ( xQueriesSupp.is() ) + xElements = xQueriesSupp->getQueries(); + else + { + Reference< XQueryDefinitionsSupplier > xQueryDefsSupp( getDataSource(), UNO_QUERY ); + if ( xQueryDefsSupp.is() ) + xElements = xQueryDefsSupp->getQueryDefinitions(); + } + } + + OSL_ENSURE( xElements.is(), "OQueryController::getObjectContainer: unable to obtain the container!" ); + return xElements; +} + +// ----------------------------------------------------------------------------- +void OQueryController::executeQuery() +{ + // we don't need to check the connection here because we already check the composer + // which can't live without his connection + ::rtl::OUString sTranslatedStmt = translateStatement( false ); + + ::rtl::OUString sDataSourceName = getDataSourceName(); + if ( sDataSourceName.getLength() && sTranslatedStmt.getLength() ) + { + try + { + getContainer()->showPreview( getFrame() ); + InvalidateFeature(SID_DB_QUERY_PREVIEW); + + URL aWantToDispatch; + aWantToDispatch.Complete = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".component:DB/DataSourceBrowser")); + + ::rtl::OUString sFrameName( FRAME_NAME_QUERY_PREVIEW ); + sal_Int32 nSearchFlags = FrameSearchFlag::CHILDREN; + + Reference< XDispatch> xDisp; + Reference< XDispatchProvider> xProv( getFrame()->findFrame( sFrameName, nSearchFlags ), UNO_QUERY ); + if(!xProv.is()) + { + xProv.set( getFrame(), UNO_QUERY ); + if (xProv.is()) + xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName, nSearchFlags); + } + else + { + xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName, FrameSearchFlag::SELF); + } + if (xDisp.is()) + { + Sequence< PropertyValue> aProps(9); + aProps[0].Name = PROPERTY_DATASOURCENAME; + aProps[0].Value <<= sDataSourceName; + + aProps[1].Name = PROPERTY_COMMAND_TYPE; + aProps[1].Value <<= CommandType::COMMAND; + + aProps[2].Name = PROPERTY_COMMAND; + aProps[2].Value <<= sTranslatedStmt; + + aProps[3].Name = PROPERTY_ENABLE_BROWSER; + aProps[3].Value = ::cppu::bool2any(sal_False); + + aProps[4].Name = PROPERTY_ACTIVE_CONNECTION; + aProps[4].Value <<= getConnection(); + + aProps[5].Name = PROPERTY_UPDATE_CATALOGNAME; + aProps[5].Value <<= m_sUpdateCatalogName; + + aProps[6].Name = PROPERTY_UPDATE_SCHEMANAME; + aProps[6].Value <<= m_sUpdateSchemaName; + + aProps[7].Name = PROPERTY_UPDATE_TABLENAME; + aProps[7].Value <<= m_sUpdateTableName; + + aProps[8].Name = PROPERTY_ESCAPE_PROCESSING; + aProps[8].Value = ::cppu::bool2any(m_bEscapeProcessing); + + xDisp->dispatch(aWantToDispatch, aProps); + // check the state of the beamer + // be notified when the beamer frame is closed + Reference< XComponent > xComponent( getFrame()->findFrame( sFrameName, nSearchFlags ), UNO_QUERY ); + if (xComponent.is()) + { + OSL_ENSURE(Reference< XFrame >(xComponent, UNO_QUERY).get() == getContainer()->getPreviewFrame().get(), + "OQueryController::executeQuery: oops ... which window do I have here?"); + Reference< XEventListener> xEvtL((::cppu::OWeakObject*)this,UNO_QUERY); + xComponent->addEventListener(xEvtL); + } + } + else + { + OSL_ENSURE(0,"Couldn't create a beamer window!"); + } + } + catch(const Exception&) + { + OSL_ENSURE(0,"Couldn't create a beamer window!"); + } + } +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryController::askForNewName(const Reference<XNameAccess>& _xElements,sal_Bool _bSaveAs) +{ + OSL_ENSURE( !editingCommand(), "OQueryController::askForNewName: not to be called when designing an independent statement!" ); + if ( editingCommand() ) + return sal_False; + + OSL_PRECOND( _xElements.is(), "OQueryController::askForNewName: invalid container!" ); + if ( !_xElements.is() ) + return sal_False; + + sal_Bool bRet = sal_True; + sal_Bool bNew = _bSaveAs || !_xElements->hasByName( m_sName ); + if(bNew) + { + String aDefaultName; + if ( ( _bSaveAs && !bNew ) || ( bNew && m_sName.getLength() ) ) + aDefaultName = String( m_sName ); + else + { + String sName = String( ModuleRes( editingView() ? STR_VIEW_TITLE : STR_QRY_TITLE ) ); + aDefaultName = sName.GetToken(0,' '); + aDefaultName = ::dbtools::createUniqueName(_xElements,aDefaultName); + } + + DynamicTableOrQueryNameCheck aNameChecker( getConnection(), CommandType::QUERY ); + OSaveAsDlg aDlg( + getView(), + m_nCommandType, + getORB(), + getConnection(), + aDefaultName, + aNameChecker, + SAD_DEFAULT ); + + bRet = ( aDlg.Execute() == RET_OK ); + if ( bRet ) + { + m_sName = aDlg.getName(); + if ( editingView() ) + { + m_sUpdateCatalogName = aDlg.getCatalog(); + m_sUpdateSchemaName = aDlg.getSchema(); + } + } + } + return bRet; +} +// ----------------------------------------------------------------------------- +bool OQueryController::doSaveAsDoc(sal_Bool _bSaveAs) +{ + OSL_ENSURE(isEditable(),"Slot ID_BROWSER_SAVEDOC should not be enabled!"); + if ( !editingCommand() && !haveDataSource() ) + { + String aMessage(ModuleRes(STR_DATASOURCE_DELETED)); + OSQLWarningBox( getView(), aMessage ).Execute(); + return false; + } + + Reference< XNameAccess > xElements = getObjectContainer(); + if ( !xElements.is() ) + return false; + + if ( !getContainer()->checkStatement() ) + return false; + + ::rtl::OUString sTranslatedStmt = translateStatement(); + if ( editingCommand() ) + { + setModified( sal_False ); + // this is all we need to do here. translateStatement implicitly set our m_sStatement, and + // notified it, and that's all + return true; + } + + if ( !sTranslatedStmt.getLength() ) + return false; + + // first we need a name for our query so ask the user + // did we get a name + ::rtl::OUString sOriginalName( m_sName ); + if ( !askForNewName( xElements, _bSaveAs ) || !m_sName.getLength() ) + return false; + + SQLExceptionInfo aInfo; + bool bSuccess = false; + bool bNew = false; + try + { + bNew = ( _bSaveAs ) + || ( !xElements->hasByName( m_sName ) ); + + Reference<XPropertySet> xQuery; + if ( bNew ) // just to make sure the query already exists + { + // drop the query, in case it already exists + if ( xElements->hasByName( m_sName ) ) + { + Reference< XDrop > xNameCont( xElements, UNO_QUERY ); + if ( xNameCont.is() ) + xNameCont->dropByName( m_sName ); + else + { + Reference< XNameContainer > xCont( xElements, UNO_QUERY ); + if ( xCont.is() ) + xCont->removeByName( m_sName ); + } + } + + // create a new (empty, uninitialized) query resp. view + Reference< XDataDescriptorFactory > xFact( xElements, UNO_QUERY ); + if ( xFact.is() ) + { + xQuery = xFact->createDataDescriptor(); + // to set the name is only allowed when the query is new + xQuery->setPropertyValue( PROPERTY_NAME, makeAny( m_sName ) ); + } + else + { + Reference< XSingleServiceFactory > xSingleFac( xElements, UNO_QUERY ); + if ( xSingleFac.is() ) + xQuery = xQuery.query( xSingleFac->createInstance() ); + } + } + else + { + xElements->getByName( m_sName ) >>= xQuery; + } + if ( !xQuery.is() ) + throw RuntimeException(); + + // the new commands + if ( editingView() && !bNew ) + { + OSL_ENSURE( xQuery == m_xAlterView, "OQueryController::doSaveAsDoc: already have another alterable view ...!?" ); + m_xAlterView.set( xQuery, UNO_QUERY_THROW ); + m_xAlterView->alterCommand( sTranslatedStmt ); + } + else + { // we're creating a query, or a *new* view + xQuery->setPropertyValue( PROPERTY_COMMAND, makeAny( sTranslatedStmt ) ); + + if ( editingView() ) + { + xQuery->setPropertyValue( PROPERTY_CATALOGNAME, makeAny( m_sUpdateCatalogName ) ); + xQuery->setPropertyValue( PROPERTY_SCHEMANAME, makeAny( m_sUpdateSchemaName ) ); + } + + if ( editingQuery() ) + { + xQuery->setPropertyValue( PROPERTY_UPDATE_TABLENAME, makeAny( m_sUpdateTableName ) ); + xQuery->setPropertyValue( PROPERTY_ESCAPE_PROCESSING,::cppu::bool2any( m_bEscapeProcessing ) ); + + xQuery->setPropertyValue( PROPERTY_LAYOUTINFORMATION, getViewData() ); + } + } + + if ( bNew ) + { + Reference< XAppend > xAppend( xElements, UNO_QUERY ); + if ( xAppend.is() ) + { + xAppend->appendByDescriptor( xQuery ); + } + else + { + Reference< XNameContainer > xCont( xElements, UNO_QUERY ); + if ( xCont.is() ) + xCont->insertByName( m_sName, makeAny( xQuery ) ); + } + + if ( editingView() ) + { + Reference< XPropertySet > xViewProps; + if ( xElements->hasByName( m_sName ) ) + xViewProps.set( xElements->getByName( m_sName ), UNO_QUERY ); + + if ( !xViewProps.is() ) // correct name and try again + m_sName = ::dbtools::composeTableName( getMetaData(), xQuery, ::dbtools::eInDataManipulation, false, false, false ); + + OSL_ENSURE( xElements->hasByName( m_sName ), "OQueryController::doSaveAsDoc: newly creaed view does not exist!" ); + + if ( xElements->hasByName( m_sName ) ) + m_xAlterView.set( xElements->getByName( m_sName ), UNO_QUERY ); + + // now check if our datasource has set a tablefilter and if so, append the new table name to it + ::dbaui::appendToFilter( getConnection(), m_sName, getORB(), getView() ); + } + Reference< XTitleChangeListener> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY); + if ( xEventListener.is() ) + { + TitleChangedEvent aEvent; + xEventListener->titleChanged(aEvent); + } + releaseNumberForComponent(); + } + + setModified( sal_False ); + bSuccess = true; + + } + catch( const SQLException& ) + { + if ( !bNew ) + m_sName = sOriginalName; + aInfo = SQLExceptionInfo( ::cppu::getCaughtException() ); + } + catch(Exception&) + { + if ( !bNew ) + m_sName = sOriginalName; + DBG_UNHANDLED_EXCEPTION(); + } + + showError( aInfo ); + + // update the title of our window + //updateTitle(); + + // if we successfully saved a view we were creating, then close the designer + if ( bSuccess && editingView() && !m_xAlterView.is() ) + { + closeTask(); + } + + if ( bSuccess && editingView() ) + InvalidateFeature( ID_BROWSER_EDITDOC ); + + return bSuccess; +} +// ----------------------------------------------------------------------------- +::rtl::OUString OQueryController::translateStatement( bool _bFireStatementChange ) +{ + // now set the properties + setStatement_fireEvent( getContainer()->getStatement(), _bFireStatementChange ); + ::rtl::OUString sTranslatedStmt; + if(m_sStatement.getLength() && m_xComposer.is() && m_bEscapeProcessing) + { + try + { + ::rtl::OUString aErrorMsg; + + ::connectivity::OSQLParseNode* pNode = m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign ); + if(pNode) + { + pNode->parseNodeToStr( sTranslatedStmt, getConnection() ); + delete pNode; + } + + m_xComposer->setQuery(sTranslatedStmt); + sTranslatedStmt = m_xComposer->getComposedQuery(); + } + catch(SQLException& e) + { + ::dbtools::SQLExceptionInfo aInfo(e); + showError(aInfo); + // an error occurred so we clear the statement + sTranslatedStmt = ::rtl::OUString(); + } + } + else if(!m_sStatement.getLength()) + { + ModuleRes aModuleRes(STR_QRY_NOSELECT); + String sTmpStr(aModuleRes); + ::rtl::OUString sError(sTmpStr); + showError(SQLException(sError,NULL,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S1000") ),1000,Any())); + } + else + sTranslatedStmt = m_sStatement; + + return sTranslatedStmt; +} +// ----------------------------------------------------------------------------- +short OQueryController::saveModified() +{ + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( getMutex() ); + short nRet = RET_YES; + if ( !isConnected() || !isModified() ) + return nRet; + + if ( !m_bGraphicalDesign + || ( !m_vTableFieldDesc.empty() + && !m_vTableData.empty() + ) + ) + { + String sMessageText( lcl_getObjectResourceString( STR_QUERY_SAVEMODIFIED, m_nCommandType ) ); + QueryBox aQry( getView(), WB_YES_NO_CANCEL | WB_DEF_YES, sMessageText ); + + nRet = aQry.Execute(); + if ( ( nRet == RET_YES ) + && !doSaveAsDoc( sal_False ) + ) + { + nRet = RET_CANCEL; + } + } + return nRet; +} +// ----------------------------------------------------------------------------- +void OQueryController::impl_reset( const bool i_bForceCurrentControllerSettings ) +{ + bool bValid = false; + + Sequence< PropertyValue > aLayoutInformation; + // get command from the query if a query name was supplied + if ( !i_bForceCurrentControllerSettings && !editingCommand() ) + { + if ( m_sName.getLength() ) + { + Reference< XNameAccess > xQueries = getObjectContainer(); + if ( xQueries.is() ) + { + Reference< XPropertySet > xProp; + if( xQueries->hasByName( m_sName ) && ( xQueries->getByName( m_sName ) >>= xProp ) && xProp.is() ) + { + ::rtl::OUString sNewStatement; + xProp->getPropertyValue( PROPERTY_COMMAND ) >>= sNewStatement; + setStatement_fireEvent( sNewStatement ); + + sal_Bool bNewEscapeProcessing( sal_True ); + if ( editingQuery() ) + { + xProp->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bNewEscapeProcessing; + setEscapeProcessing_fireEvent( bNewEscapeProcessing ); + } + + m_bGraphicalDesign = m_bGraphicalDesign && m_bEscapeProcessing; + bValid = true; + + try + { + if ( editingQuery() ) + xProp->getPropertyValue( PROPERTY_LAYOUTINFORMATION ) >>= aLayoutInformation; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OQueryController::impl_reset: could not retrieve the layout information from the query!" ); + } + } + } + } + } + else + { + bValid = true; + // assume that we got all necessary information during initialization + } + + if ( bValid ) + { + // load the layoutInformation + if ( aLayoutInformation.getLength() ) + { + try + { + loadViewSettings( aLayoutInformation ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + if ( m_sStatement.getLength() ) + { + setQueryComposer(); + + bool bError( false ); + + if ( !m_pSqlIterator ) + { + bError = true; + } + else if ( m_bEscapeProcessing ) + { + ::rtl::OUString aErrorMsg; + ::std::auto_ptr< ::connectivity::OSQLParseNode > pNode( + m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign ) ); + + if ( pNode.get() ) + { + delete m_pSqlIterator->getParseTree(); + m_pSqlIterator->setParseTree( pNode.release() ); + m_pSqlIterator->traverseAll(); + if ( m_pSqlIterator->hasErrors() ) + { + if ( !i_bForceCurrentControllerSettings && m_bGraphicalDesign && !editingView() ) + { + impl_showAutoSQLViewError( makeAny( m_pSqlIterator->getErrors() ) ); + } + bError = true; + } + } + else + { + if ( !i_bForceCurrentControllerSettings && !editingView() ) + { + String aTitle(ModuleRes(STR_SVT_SQL_SYNTAX_ERROR)); + OSQLMessageBox aDlg(getView(),aTitle,aErrorMsg); + aDlg.Execute(); + } + bError = true; + } + } + + if ( bError ) + { + m_bGraphicalDesign = sal_False; + if ( editingView() ) + // if we're editing a view whose statement could not be parsed, default to "no escape processing" + setEscapeProcessing_fireEvent( sal_False ); + } + } + } + + if(!m_pSqlIterator) + setQueryComposer(); + OSL_ENSURE(m_pSqlIterator,"No SQLIterator set!"); + + getContainer()->setNoneVisbleRow(m_nVisibleRows); +} + +// ----------------------------------------------------------------------------- +void OQueryController::reset() +{ + impl_reset(); + getContainer()->reset( NULL ); + getUndoMgr()->Clear(); +} + +// ----------------------------------------------------------------------------- +void OQueryController::setStatement_fireEvent( const ::rtl::OUString& _rNewStatement, bool _bFireStatementChange ) +{ + Any aOldValue = makeAny( m_sStatement ); + m_sStatement = _rNewStatement; + Any aNewValue = makeAny( m_sStatement ); + + sal_Int32 nHandle = PROPERTY_ID_ACTIVECOMMAND; + if ( _bFireStatementChange ) + fire( &nHandle, &aNewValue, &aOldValue, 1, sal_False ); +} + +// ----------------------------------------------------------------------------- +void OQueryController::setEscapeProcessing_fireEvent( const sal_Bool _bEscapeProcessing ) +{ + if ( _bEscapeProcessing == m_bEscapeProcessing ) + return; + + Any aOldValue = makeAny( m_bEscapeProcessing ); + m_bEscapeProcessing = _bEscapeProcessing; + Any aNewValue = makeAny( m_bEscapeProcessing ); + + sal_Int32 nHandle = PROPERTY_ID_ESCAPE_PROCESSING; + fire( &nHandle, &aNewValue, &aOldValue, 1, sal_False ); +} + +// ----------------------------------------------------------------------------- +IMPL_LINK( OQueryController, OnExecuteAddTable, void*, /*pNotInterestedIn*/ ) +{ + Execute( ID_BROWSER_ADDTABLE,Sequence<PropertyValue>() ); + return 0L; +} + +// ----------------------------------------------------------------------------- +bool OQueryController::allowViews() const +{ + return true; +} + +// ----------------------------------------------------------------------------- +bool OQueryController::allowQueries() const +{ + DBG_ASSERT( getSdbMetaData().isConnected(), "OQueryController::allowQueries: illegal call!" ); + if ( !getSdbMetaData().supportsSubqueriesInFrom() ) + return false; + + const NamedValueCollection& rArguments( getInitParams() ); + sal_Int32 nCommandType = rArguments.getOrDefault( (::rtl::OUString)PROPERTY_COMMAND_TYPE, (sal_Int32)CommandType::QUERY ); + sal_Bool bCreatingView = ( nCommandType == CommandType::TABLE ); + return !bCreatingView; +} + +// ----------------------------------------------------------------------------- +Any SAL_CALL OQueryController::getViewData() throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard( getMutex() ); + + getContainer()->SaveUIConfig(); + + ::comphelper::NamedValueCollection aViewSettings; + saveViewSettings( aViewSettings, false ); + + return makeAny( aViewSettings.getPropertyValues() ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQueryController::restoreViewData(const Any& /*Data*/) throw( RuntimeException ) +{ + // TODO +} + +// ----------------------------------------------------------------------------- +} // namespace dbaui +// ----------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/querydlg.cxx b/dbaccess/source/ui/querydesign/querydlg.cxx new file mode 100644 index 000000000000..d2fb74b53327 --- /dev/null +++ b/dbaccess/source/ui/querydesign/querydlg.cxx @@ -0,0 +1,375 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "querydlg.hxx" +#include "dbu_qry.hrc" +#include "querydlg.hrc" +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include "QTableConnectionData.hxx" +#include "querycontroller.hxx" +#include "QueryTableView.hxx" +#include "QueryDesignView.hxx" +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include "RelationControl.hxx" +#include <vcl/msgbox.hxx> + +using namespace dbaui; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::sdbc; + +namespace dbaui +{ +class OJoinControl : public Window +{ +public: + FixedLine aFL_Join; + FixedText aFT_Title; + ListBox aLB_JoinType; + CheckBox m_aCBNatural; + + OJoinControl(Window* _pParent,const ResId& _rResId); +}; +OJoinControl::OJoinControl(Window* _pParent,const ResId& _rResId) + : Window(_pParent,_rResId) + ,aFL_Join( this, ResId( FL_JOIN,*_rResId.GetResMgr() ) ) + ,aFT_Title( this, ResId(FT_LISTBOXTITLE,*_rResId.GetResMgr()) ) + ,aLB_JoinType( this, ResId(LB_JOINTYPE,*_rResId.GetResMgr()) ) + ,m_aCBNatural( this, ResId(CB_NATURAL,*_rResId.GetResMgr()) ) +{ + FreeResource(); +} +// ----------------------------------------------------------------------------- +} // dbaui +// ----------------------------------------------------------------------------- +DBG_NAME(DlgQryJoin) +DlgQryJoin::DlgQryJoin( OQueryTableView * pParent, + const TTableConnectionData::value_type& _pData, + OJoinTableView::OTableWindowMap* _pTableMap, + const Reference< XConnection >& _xConnection, + BOOL _bAllowTableSelect) + :ModalDialog( pParent, ModuleRes(DLG_QRY_JOIN) ) + ,aML_HelpText( this, ModuleRes(ML_HELPTEXT) ) + ,aPB_OK( this, ModuleRes( PB_OK ) ) + ,aPB_CANCEL( this, ModuleRes( PB_CANCEL ) ) + ,aPB_HELP( this, ModuleRes( PB_HELP ) ) + ,m_pJoinControl( NULL ) + ,m_pTableControl( NULL ) + ,m_pTableMap(_pTableMap) + ,m_pTableView(pParent) + ,eJoinType(static_cast<OQueryTableConnectionData*>(_pData.get())->GetJoinType()) + ,m_pOrigConnData(_pData) + ,m_xConnection(_xConnection) +{ + DBG_CTOR(DlgQryJoin,NULL); + + aML_HelpText.SetControlBackground( GetSettings().GetStyleSettings().GetFaceColor() ); + ////////////////////////////////////////////////////////////////////// + // Connection kopieren + m_pConnData.reset(_pData->NewInstance()); + m_pConnData->CopyFrom(*_pData); + + m_pTableControl = new OTableListBoxControl(this,ModuleRes(WND_CONTROL),m_pTableMap,this); + + m_pJoinControl = new OJoinControl(m_pTableControl,ModuleRes(WND_JOIN_CONTROL)); + + m_pJoinControl->Show(); + m_pJoinControl->m_aCBNatural.Check(static_cast<OQueryTableConnectionData*>(m_pConnData.get())->isNatural()); + m_pTableControl->Show(); + + if( _bAllowTableSelect ) + { + m_pTableControl->Init( m_pConnData ); + m_pTableControl->fillListBoxes(); + } + else + { + m_pTableControl->fillAndDisable(m_pConnData); + m_pTableControl->Init( m_pConnData ); + } + + m_pTableControl->lateUIInit(m_pJoinControl); + + sal_Bool bSupportFullJoin = sal_False; + Reference<XDatabaseMetaData> xMeta; + try + { + xMeta = m_xConnection->getMetaData(); + if ( xMeta.is() ) + bSupportFullJoin = xMeta->supportsFullOuterJoins(); + } + catch(SQLException&) + { + } + sal_Bool bSupportOuterJoin = sal_False; + try + { + if ( xMeta.is() ) + bSupportOuterJoin= xMeta->supportsOuterJoins(); + } + catch(SQLException&) + { + } + + setJoinType(eJoinType); + + aPB_OK.SetClickHdl( LINK(this, DlgQryJoin, OKClickHdl) ); + + m_pJoinControl->aLB_JoinType.SetSelectHdl(LINK(this,DlgQryJoin,LBChangeHdl)); + m_pJoinControl->m_aCBNatural.SetToggleHdl(LINK(this,DlgQryJoin,NaturalToggleHdl)); + + if ( static_cast<OQueryTableView*>(pParent)->getDesignView()->getController().isReadOnly() ) + { + m_pJoinControl->aLB_JoinType.Disable(); + m_pJoinControl->m_aCBNatural.Disable(); + m_pTableControl->Disable(); + } + else + { + const USHORT nCount = m_pJoinControl->aLB_JoinType.GetEntryCount(); + for (USHORT i = 0; i < nCount; ++i) + { + const long nJoinTyp = reinterpret_cast<long>(m_pJoinControl->aLB_JoinType.GetEntryData(i)); + if ( !bSupportFullJoin && nJoinTyp == ID_FULL_JOIN ) + m_pJoinControl->aLB_JoinType.RemoveEntry(i); + else if ( !bSupportOuterJoin && (nJoinTyp == ID_LEFT_JOIN || nJoinTyp == ID_RIGHT_JOIN) ) + m_pJoinControl->aLB_JoinType.RemoveEntry(i); + } + + m_pTableControl->NotifyCellChange(); + m_pTableControl->enableRelation(!static_cast<OQueryTableConnectionData*>(m_pConnData.get())->isNatural() && eJoinType != CROSS_JOIN ); + } + + FreeResource(); +} + +//------------------------------------------------------------------------ +DlgQryJoin::~DlgQryJoin() +{ + DBG_DTOR(DlgQryJoin,NULL); + delete m_pJoinControl; + delete m_pTableControl; +} +// ----------------------------------------------------------------------------- +IMPL_LINK( DlgQryJoin, LBChangeHdl, ListBox*, /*pListBox*/ ) +{ + DBG_CHKTHIS(DlgQryJoin,NULL); + if (m_pJoinControl->aLB_JoinType.GetSelectEntryPos() == m_pJoinControl->aLB_JoinType.GetSavedValue() ) + return 1; + + m_pJoinControl->aLB_JoinType.SaveValue(); + aML_HelpText.SetText(String()); + + m_pTableControl->enableRelation(true); + + String sFirstWinName = m_pConnData->getReferencingTable()->GetWinName(); + String sSecondWinName = m_pConnData->getReferencedTable()->GetWinName(); + const EJoinType eOldJoinType = eJoinType; + USHORT nResId = 0; + const USHORT nPos = m_pJoinControl->aLB_JoinType.GetSelectEntryPos(); + const long nJoinType = reinterpret_cast<long>(m_pJoinControl->aLB_JoinType.GetEntryData(nPos)); + sal_Bool bAddHint = sal_True; + switch ( nJoinType ) + { + default: + case ID_INNER_JOIN: + nResId = STR_QUERY_INNER_JOIN; + bAddHint = sal_False; + eJoinType = INNER_JOIN; + break; + case ID_LEFT_JOIN: + nResId = STR_QUERY_LEFTRIGHT_JOIN; + eJoinType = LEFT_JOIN; + break; + case ID_RIGHT_JOIN: + { + nResId = STR_QUERY_LEFTRIGHT_JOIN; + eJoinType = RIGHT_JOIN; + String sTemp = sFirstWinName; + sFirstWinName = sSecondWinName; + sSecondWinName = sTemp; + } + break; + case ID_FULL_JOIN: + nResId = STR_QUERY_FULL_JOIN; + eJoinType = FULL_JOIN; + break; + case ID_CROSS_JOIN: + { + nResId = STR_QUERY_CROSS_JOIN; + eJoinType = CROSS_JOIN; + + m_pConnData->ResetConnLines(); + m_pTableControl->lateInit(); + m_pJoinControl->m_aCBNatural.Check(FALSE); + m_pTableControl->enableRelation(false); + ::rtl::OUString sEmpty; + m_pConnData->AppendConnLine(sEmpty,sEmpty); + aPB_OK.Enable(TRUE); + } + break; + } + + m_pJoinControl->m_aCBNatural.Enable(eJoinType != CROSS_JOIN); + + if ( eJoinType != eOldJoinType && eOldJoinType == CROSS_JOIN ) + { + m_pConnData->ResetConnLines(); + } + if ( eJoinType != CROSS_JOIN ) + { + m_pTableControl->NotifyCellChange(); + NaturalToggleHdl(&m_pJoinControl->m_aCBNatural); + } + + m_pTableControl->Invalidate(); + + String sHelpText = String( ModuleRes( nResId ) ); + if( nPos ) + { + sHelpText.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "%1" ) ), sFirstWinName ); + sHelpText.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "%2" ) ), sSecondWinName ); + } + if ( bAddHint ) + { + sHelpText += String( RTL_CONSTASCII_USTRINGPARAM( "\n" ) ); + sHelpText += String( ModuleRes( STR_JOIN_TYPE_HINT ) ); + } + + aML_HelpText.SetText( sHelpText ); + return 1; +} +// ----------------------------------------------------------------------------- + +IMPL_LINK( DlgQryJoin, OKClickHdl, Button*, /*pButton*/ ) +{ + DBG_CHKTHIS(DlgQryJoin,NULL); + + m_pConnData->Update(); + m_pOrigConnData->CopyFrom( *m_pConnData ); + + EndDialog(RET_OK); + return 1; +} +// ----------------------------------------------------------------------------- + +IMPL_LINK( DlgQryJoin, NaturalToggleHdl, CheckBox*, /*pButton*/ ) +{ + DBG_CHKTHIS(DlgQryJoin,NULL); + BOOL bChecked = m_pJoinControl->m_aCBNatural.IsChecked(); + static_cast<OQueryTableConnectionData*>(m_pConnData.get())->setNatural(bChecked); + m_pTableControl->enableRelation(!bChecked); + if ( bChecked ) + { + m_pConnData->ResetConnLines(); + try + { + Reference<XNameAccess> xReferencedTableColumns(m_pConnData->getReferencedTable()->getColumns()); + Sequence< ::rtl::OUString> aSeq = m_pConnData->getReferencingTable()->getColumns()->getElementNames(); + const ::rtl::OUString* pIter = aSeq.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); + for(;pIter != pEnd;++pIter) + { + if ( xReferencedTableColumns->hasByName(*pIter) ) + m_pConnData->AppendConnLine(*pIter,*pIter); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + m_pTableControl->NotifyCellChange(); + m_pTableControl->Invalidate(); + } + + return 1; +} +// ----------------------------------------------------------------------------- +TTableConnectionData::value_type DlgQryJoin::getConnectionData() const +{ + return m_pConnData; +} +// ----------------------------------------------------------------------------- +void DlgQryJoin::setValid(sal_Bool _bValid) +{ + aPB_OK.Enable(_bValid || eJoinType == CROSS_JOIN ); +} +// ----------------------------------------------------------------------------- +void DlgQryJoin::notifyConnectionChange( ) +{ + setJoinType( static_cast<OQueryTableConnectionData*>(m_pConnData.get())->GetJoinType() ); + m_pJoinControl->m_aCBNatural.Check(static_cast<OQueryTableConnectionData*>(m_pConnData.get())->isNatural()); + NaturalToggleHdl(&m_pJoinControl->m_aCBNatural); +} +// ----------------------------------------------------------------------------- +void DlgQryJoin::setJoinType(EJoinType _eNewJoinType) +{ + eJoinType = _eNewJoinType; + m_pJoinControl->m_aCBNatural.Enable(eJoinType != CROSS_JOIN); + + long nJoinType = 0; + switch ( eJoinType ) + { + default: + case INNER_JOIN: + nJoinType = ID_INNER_JOIN; + break; + case LEFT_JOIN: + nJoinType = ID_LEFT_JOIN; + break; + case RIGHT_JOIN: + nJoinType = ID_RIGHT_JOIN; + break; + case FULL_JOIN: + nJoinType = ID_FULL_JOIN; + break; + case CROSS_JOIN: + nJoinType = ID_CROSS_JOIN; + break; + } + + const USHORT nCount = m_pJoinControl->aLB_JoinType.GetEntryCount(); + for (USHORT i = 0; i < nCount; ++i) + { + if ( nJoinType == reinterpret_cast<long>(m_pJoinControl->aLB_JoinType.GetEntryData(i)) ) + { + m_pJoinControl->aLB_JoinType.SelectEntryPos(i); + break; + } + } + + LBChangeHdl(&m_pJoinControl->aLB_JoinType); +} +// ----------------------------------------------------------------------------- + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/querydlg.hrc b/dbaccess/source/ui/querydesign/querydlg.hrc new file mode 100644 index 000000000000..0112fe1ffa56 --- /dev/null +++ b/dbaccess/source/ui/querydesign/querydlg.hrc @@ -0,0 +1,61 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef DBAUI_QUERYDLG_HRC +#define DBAUI_QUERYDLG_HRC + +#ifndef DBACCESS_SOURCE_UI_INC_RELATIONCONTROL_HRC +#include "RelationControl.hrc" +#endif + +#define FL_JOIN 1 +#define FT_LISTBOXTITLE 2 + +#define LB_JOINTYPE 1 + +#define GB_FIELDS 1 + +#define CB_NATURAL 1 + +#define PB_OK 1 +#define PB_CANCEL 2 +#define PB_HELP 3 +#define ML_HELPTEXT 4 + +#define WND_JOIN_CONTROL 1 +#define WND_CONTROL 2 + +#define ID_INNER_JOIN 1 +#define ID_LEFT_JOIN 2 +#define ID_RIGHT_JOIN 3 +#define ID_FULL_JOIN 4 +#define ID_CROSS_JOIN 5 + +#endif // DBAUI_QUERYDLG_HRC + + + diff --git a/dbaccess/source/ui/querydesign/querydlg.hxx b/dbaccess/source/ui/querydesign/querydlg.hxx new file mode 100644 index 000000000000..2e0b331fb13e --- /dev/null +++ b/dbaccess/source/ui/querydesign/querydlg.hxx @@ -0,0 +1,108 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DBAUI_QUERYDLG_HXX +#define DBAUI_QUERYDLG_HXX +#include <vcl/dialog.hxx> + +#include <vcl/button.hxx> + +#include <vcl/fixed.hxx> +#include <vcl/lstbox.hxx> + +#include "QEnumTypes.hxx" + +#include "RelControliFace.hxx" +#include "JoinTableView.hxx" + + +namespace dbaui +{ + class OQueryTableConnectionData; + class OTableListBoxControl; + class OQueryTableView; + class OJoinControl; + class DlgQryJoin : public ModalDialog + ,public IRelationControlInterface + { + protected: + FixedText aML_HelpText; + OKButton aPB_OK; + CancelButton aPB_CANCEL; + HelpButton aPB_HELP; + + OJoinControl* m_pJoinControl; + OTableListBoxControl* m_pTableControl; + OJoinTableView::OTableWindowMap* m_pTableMap; + OQueryTableView* m_pTableView; + + EJoinType eJoinType; + TTableConnectionData::value_type m_pConnData; // enth"alt linke und rechte Tabelle + TTableConnectionData::value_type m_pOrigConnData; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xConnection; + + + DECL_LINK( OKClickHdl, Button* ); + DECL_LINK( LBChangeHdl, ListBox* ); + DECL_LINK( NaturalToggleHdl, CheckBox* ); + + /** setJoinType enables and set the new join type + @param _eNewJoinType the new jointype + */ + void setJoinType(EJoinType _eNewJoinType); + public: + DlgQryJoin( OQueryTableView * pParent, + const TTableConnectionData::value_type& pData, + OJoinTableView::OTableWindowMap* _pTableMap, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _xConnection, + BOOL _bAllowTableSelect); + virtual ~DlgQryJoin(); + EJoinType GetJoinType() const { return eJoinType; }; + + /** getConnectionData returns the current connection data + @return the current connectiondata + */ + virtual TTableConnectionData::value_type getConnectionData() const; + + /** setValid set the valid inside, can be used for OK buttons + @param _bValid true when the using control allows an update + */ + virtual void setValid(sal_Bool _bValid); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > getConnection() { return m_xConnection; } + + /** notifyConnectionChange is callback which is called when the table selection has changed and a new connection exists + @param _pConnectionData the connection which exists between the new tables + */ + virtual void notifyConnectionChange(); + }; +} +#endif // DBAUI_QUERYDLG_HXX + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/querydesign/querydlg.src b/dbaccess/source/ui/querydesign/querydlg.src new file mode 100644 index 000000000000..fe8f32da49a1 --- /dev/null +++ b/dbaccess/source/ui/querydesign/querydlg.src @@ -0,0 +1,194 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _DBU_QRY_HRC_ +#include "dbu_qry.hrc" +#endif +#ifndef DBAUI_QUERYDLG_HRC +#include "querydlg.hrc" +#endif +#include "dbaccess_helpid.hrc" + +ModalDialog DLG_QRY_JOIN +{ + OutputSize = TRUE ; + SVLook = TRUE ; + HelpId = HID_DLG_QRY_JOIN ; + Size = MAP_APPFONT ( 265, 219 ) ; + + Moveable = TRUE ; + Closeable = TRUE ; + + Window WND_JOIN_CONTROL + { + Pos = MAP_APPFONT( 0, 0 ); + Size = MAP_APPFONT( 203, 44 ); + DialogControl = TRUE; + HelpId = HID_DLG_QRY_JOIN_CONTROL ; + FixedLine FL_JOIN + { + Pos = MAP_APPFONT ( 6 , 3 ) ; + Size = MAP_APPFONT ( 191 , 8 ) ; + Text [ en-US ] = "Options"; + }; + + FixedText FT_LISTBOXTITLE + { + Pos = MAP_APPFONT ( 12 , 16 ) ; + Size = MAP_APPFONT ( 89 , 8 ) ; + + Text [ en-US ] = "~Type"; + }; + + ListBox LB_JOINTYPE + { + Pos = MAP_APPFONT ( 101 , 15 ) ; + Size = MAP_APPFONT ( 90 , 60 ) ; + HelpId = HID_DLG_QRY_JOINTYPE ; + + DropDown = TRUE; + DDExtraWidth = TRUE; + StringList [ en-US ] = + { + < "Inner join" ; ID_INNER_JOIN; > ; + < "Left join" ; ID_LEFT_JOIN; > ; + < "Right join" ; ID_RIGHT_JOIN; > ; + < "Full (outer) join" ; ID_FULL_JOIN; > ; + < "Cross join" ; ID_CROSS_JOIN; > ; + }; + }; + CheckBox CB_NATURAL + { + Pos = MAP_APPFONT ( 101 , 31 ) ; + Size = MAP_APPFONT ( 89 , 8 ) ; + + Text [ en-US ] = "Natural"; + }; + }; + + Window WND_CONTROL + { + Pos = MAP_APPFONT( 0, 0 ); + Size = MAP_APPFONT( 203, 153 ); + DialogControl = TRUE; + HelpId = HID_DLG_QRY_WINDOW_CONTROL ; + + FixedLine FL_INVOLVED_TABLES + { + Pos = MAP_APPFONT ( 6 , 3 ) ; + Size = MAP_APPFONT ( 191 , 8 ) ; + Text [ en-US ] = "Tables involved"; + }; + + ListBox LB_LEFT_TABLE + { + Border = TRUE; + Pos = MAP_APPFONT( 12, 14 ); + Size = MAP_APPFONT( 87, 60 ); + HelpId = HID_DLG_QRY_LEFT_TABLE ; + DropDown = TRUE; + TabStop = TRUE; + }; + + ListBox LB_RIGHT_TABLE + { + Border = TRUE; + Pos = MAP_APPFONT( 104, 14 ); + Size = MAP_APPFONT( 87, 60 ); + HelpId = HID_DLG_QRY_RIGHT_TABLE ; + DropDown = TRUE; + TabStop = TRUE; + }; + + FixedLine FL_INVOLVED_FIELDS + { + Pos = MAP_APPFONT ( 6 , 29 ) ; + Size = MAP_APPFONT ( 191 , 8 ) ; + Text [ en-US ] = "Fields involved"; + }; + }; + + FixedText ML_HELPTEXT + { + Pos = MAP_APPFONT ( 12 , 159 ) ; + Size = MAP_APPFONT ( 179 , 49 ) ; + UniqueId = HID_DLG_QRY_HELPTEXT ; + SVLook = TRUE; + WordBreak = TRUE; + }; + + OKButton PB_OK + { + Pos = MAP_APPFONT ( 206 , 6 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + DefButton = TRUE ; + }; + CancelButton PB_CANCEL + { + Pos = MAP_APPFONT ( 206 , 23 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + HelpButton PB_HELP + { + Pos = MAP_APPFONT ( 206 , 43 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + + Text [ en-US ] = "Join Properties"; +}; + +String STR_JOIN_TYPE_HINT +{ + Text [ en-US ] = "Please note that some databases may not support this join type."; +}; + +String STR_QUERY_INNER_JOIN +{ + Text [ en-US ] = "Includes only records for which the contents of the related fields of both tables are identical."; +}; + +String STR_QUERY_LEFTRIGHT_JOIN +{ + Text [ en-US ] = "Contains ALL records from table '%1' but only records from table '%2' where the values in the related fields are matching."; +}; + +String STR_QUERY_FULL_JOIN +{ + Text [ en-US ] = "Contains ALL records from '%1' and from '%2'."; +}; + +String STR_QUERY_CROSS_JOIN +{ + Text [ en-US ] = "Contains the cartesian product of ALL records from '%1' and from '%2'."; +}; + +String STR_QUERY_NATURAL_JOIN +{ + Text [ en-US ] = "Contains only one column for each pair of equally-named columns from '%1' and from '%2'."; +}; diff --git a/dbaccess/source/ui/querydesign/queryview.cxx b/dbaccess/source/ui/querydesign/queryview.cxx new file mode 100644 index 000000000000..dea455795484 --- /dev/null +++ b/dbaccess/source/ui/querydesign/queryview.cxx @@ -0,0 +1,58 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "queryview.hxx" +#include "dbu_qry.hrc" +#include "querycontroller.hxx" + + +using namespace dbaui; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +DBG_NAME(OQueryView) +// ------------------------------------------------------------------------- +OQueryView::OQueryView(Window* _pParent, OQueryController& _rController,const Reference< XMultiServiceFactory >& _rFactory) + :OJoinDesignView( _pParent, _rController, _rFactory ) +{ + DBG_CTOR(OQueryView,NULL); + +} +// ----------------------------------------------------------------------------- +OQueryView::~OQueryView() +{ + + DBG_DTOR(OQueryView,NULL); +} +// ----------------------------------------------------------------------------- + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |