1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
30 #ifndef DBAUI_QUERYDLG_HXX
31 #include "querydlg.hxx"
32 #endif
33 #ifndef _DBU_QRY_HRC_
34 #include "dbu_qry.hrc"
35 #endif
36 #ifndef DBAUI_QUERYDLG_HRC
37 #include "querydlg.hrc"
38 #endif
39 #ifndef _TOOLS_DEBUG_HXX
40 #include <tools/debug.hxx>
41 #endif
42 #ifndef TOOLS_DIAGNOSE_EX_H
43 #include <tools/diagnose_ex.h>
44 #endif
45 #ifndef DBAUI_QTABLECONNECTIONDATA_HXX
46 #include "QTableConnectionData.hxx"
47 #endif
48 #ifndef DBAUI_QUERYCONTROLLER_HXX
49 #include "querycontroller.hxx"
50 #endif
51 #ifndef DBAUI_QUERYTABLEVIEW_HXX
52 #include "QueryTableView.hxx"
53 #endif
54 #ifndef DBAUI_QUERYDESIGNVIEW_HXX
55 #include "QueryDesignView.hxx"
56 #endif
57 #ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_
58 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
59 #endif
60 #ifndef DBAUI_RELATIONCONTROL_HXX
61 #include "RelationControl.hxx"
62 #endif
63 #ifndef _SV_MSGBOX_HXX
64 #include <vcl/msgbox.hxx>
65 #endif
66 
67 using namespace dbaui;
68 using namespace ::com::sun::star::uno;
69 using namespace ::com::sun::star::container;
70 using namespace ::com::sun::star::sdbc;
71 
72 namespace dbaui
73 {
74 class OJoinControl 	: public Window
75 {
76 public:
77     FixedLine				aFL_Join;
78 	FixedText				aFT_Title;
79 	ListBox					aLB_JoinType;
80     CheckBox                m_aCBNatural;
81 
82 	OJoinControl(Window* _pParent,const ResId& _rResId);
83 };
84 OJoinControl::OJoinControl(Window* _pParent,const ResId& _rResId)
85     : Window(_pParent,_rResId)
86     ,aFL_Join( this, ResId( FL_JOIN,*_rResId.GetResMgr() ) )
87     ,aFT_Title( this, ResId(FT_LISTBOXTITLE,*_rResId.GetResMgr()) )
88     ,aLB_JoinType( this, ResId(LB_JOINTYPE,*_rResId.GetResMgr()) )
89     ,m_aCBNatural( this, ResId(CB_NATURAL,*_rResId.GetResMgr()) )
90 {
91     FreeResource();
92 }
93 // -----------------------------------------------------------------------------
94 } // dbaui
95 // -----------------------------------------------------------------------------
96 DBG_NAME(DlgQryJoin)
97 DlgQryJoin::DlgQryJoin( OQueryTableView * pParent,
98 					   const TTableConnectionData::value_type& _pData,
99 					   OJoinTableView::OTableWindowMap*	_pTableMap,
100 					   const Reference< XConnection >& _xConnection,
101 					   sal_Bool _bAllowTableSelect)
102     :ModalDialog( pParent, ModuleRes(DLG_QRY_JOIN) )
103     ,aML_HelpText( this, ModuleRes(ML_HELPTEXT) )
104     ,aPB_OK( this, ModuleRes( PB_OK ) )
105     ,aPB_CANCEL( this, ModuleRes( PB_CANCEL ) )
106     ,aPB_HELP( this, ModuleRes( PB_HELP ) )
107     ,m_pJoinControl( NULL )
108     ,m_pTableControl( NULL )
109     ,m_pTableMap(_pTableMap)
110     ,m_pTableView(pParent)
111     ,eJoinType(static_cast<OQueryTableConnectionData*>(_pData.get())->GetJoinType())
112     ,m_pOrigConnData(_pData)
113     ,m_xConnection(_xConnection)
114 {
115 	DBG_CTOR(DlgQryJoin,NULL);
116 
117 	aML_HelpText.SetControlBackground( GetSettings().GetStyleSettings().GetFaceColor() );
118 	//////////////////////////////////////////////////////////////////////
119 	// Connection kopieren
120 	m_pConnData.reset(_pData->NewInstance());
121 	m_pConnData->CopyFrom(*_pData);
122 
123 	m_pTableControl = new OTableListBoxControl(this,ModuleRes(WND_CONTROL),m_pTableMap,this);
124 
125     m_pJoinControl = new OJoinControl(m_pTableControl,ModuleRes(WND_JOIN_CONTROL));
126 
127     m_pJoinControl->Show();
128     m_pJoinControl->m_aCBNatural.Check(static_cast<OQueryTableConnectionData*>(m_pConnData.get())->isNatural());
129     m_pTableControl->Show();
130 
131 	if( _bAllowTableSelect )
132 	{
133 		m_pTableControl->Init( m_pConnData );
134 		m_pTableControl->fillListBoxes();
135 	}
136 	else
137 	{
138 		m_pTableControl->fillAndDisable(m_pConnData);
139 		m_pTableControl->Init( m_pConnData );
140 	}
141 
142 	m_pTableControl->lateUIInit(m_pJoinControl);
143 
144     sal_Bool bSupportFullJoin = sal_False;
145 	Reference<XDatabaseMetaData> xMeta;
146 	try
147 	{
148 		xMeta = m_xConnection->getMetaData();
149 		if ( xMeta.is() )
150 			bSupportFullJoin = xMeta->supportsFullOuterJoins();
151 	}
152 	catch(SQLException&)
153 	{
154 	}
155     sal_Bool bSupportOuterJoin = sal_False;
156 	try
157 	{
158 		if ( xMeta.is() )
159 			bSupportOuterJoin= xMeta->supportsOuterJoins();
160 	}
161 	catch(SQLException&)
162 	{
163 	}
164 
165 	setJoinType(eJoinType);
166 
167 	aPB_OK.SetClickHdl( LINK(this, DlgQryJoin, OKClickHdl) );
168 
169 	m_pJoinControl->aLB_JoinType.SetSelectHdl(LINK(this,DlgQryJoin,LBChangeHdl));
170     m_pJoinControl->m_aCBNatural.SetToggleHdl(LINK(this,DlgQryJoin,NaturalToggleHdl));
171 
172 	if ( static_cast<OQueryTableView*>(pParent)->getDesignView()->getController().isReadOnly() )
173 	{
174 		m_pJoinControl->aLB_JoinType.Disable();
175         m_pJoinControl->m_aCBNatural.Disable();
176 		m_pTableControl->Disable();
177 	}
178 	else
179 	{
180         const sal_uInt16 nCount = m_pJoinControl->aLB_JoinType.GetEntryCount();
181         for (sal_uInt16 i = 0; i < nCount; ++i)
182         {
183             const long nJoinTyp = reinterpret_cast<long>(m_pJoinControl->aLB_JoinType.GetEntryData(i));
184             if ( !bSupportFullJoin && nJoinTyp == ID_FULL_JOIN )
185                 m_pJoinControl->aLB_JoinType.RemoveEntry(i);
186             else if ( !bSupportOuterJoin && (nJoinTyp == ID_LEFT_JOIN || nJoinTyp == ID_RIGHT_JOIN) )
187                 m_pJoinControl->aLB_JoinType.RemoveEntry(i);
188         }
189 
190 		m_pTableControl->NotifyCellChange();
191         m_pTableControl->enableRelation(!static_cast<OQueryTableConnectionData*>(m_pConnData.get())->isNatural() && eJoinType != CROSS_JOIN );
192 	}
193 
194 	FreeResource();
195 }
196 
197 //------------------------------------------------------------------------
198 DlgQryJoin::~DlgQryJoin()
199 {
200 	DBG_DTOR(DlgQryJoin,NULL);
201     delete m_pJoinControl;
202 	delete m_pTableControl;
203 }
204 // -----------------------------------------------------------------------------
205 IMPL_LINK( DlgQryJoin, LBChangeHdl, ListBox*, /*pListBox*/ )
206 {
207 	DBG_CHKTHIS(DlgQryJoin,NULL);
208     if (m_pJoinControl->aLB_JoinType.GetSelectEntryPos() == m_pJoinControl->aLB_JoinType.GetSavedValue() )
209         return 1;
210 
211     m_pJoinControl->aLB_JoinType.SaveValue();
212 	aML_HelpText.SetText(String());
213 
214     m_pTableControl->enableRelation(true);
215 
216     String sFirstWinName	= m_pConnData->getReferencingTable()->GetWinName();
217     String sSecondWinName	= m_pConnData->getReferencedTable()->GetWinName();
218     const EJoinType eOldJoinType = eJoinType;
219 	sal_uInt16 nResId = 0;
220 	const sal_uInt16 nPos = m_pJoinControl->aLB_JoinType.GetSelectEntryPos();
221     const long nJoinType = reinterpret_cast<long>(m_pJoinControl->aLB_JoinType.GetEntryData(nPos));
222     sal_Bool bAddHint = sal_True;
223 	switch ( nJoinType )
224 	{
225 		default:
226 		case ID_INNER_JOIN:
227 			nResId = STR_QUERY_INNER_JOIN;
228             bAddHint = sal_False;
229             eJoinType = INNER_JOIN;
230 			break;
231 		case ID_LEFT_JOIN:
232             nResId = STR_QUERY_LEFTRIGHT_JOIN;
233             eJoinType = LEFT_JOIN;
234             break;
235         case ID_RIGHT_JOIN:
236             {
237 			    nResId = STR_QUERY_LEFTRIGHT_JOIN;
238                 eJoinType = RIGHT_JOIN;
239                 String sTemp = sFirstWinName;
240                 sFirstWinName = sSecondWinName;
241                 sSecondWinName = sTemp;
242             }
243 			break;
244 		case ID_FULL_JOIN:
245 			nResId = STR_QUERY_FULL_JOIN;
246             eJoinType = FULL_JOIN;
247 			break;
248         case ID_CROSS_JOIN:
249             {
250                 nResId = STR_QUERY_CROSS_JOIN;
251                 eJoinType = CROSS_JOIN;
252 
253                 m_pConnData->ResetConnLines();
254                 m_pTableControl->lateInit();
255                 m_pJoinControl->m_aCBNatural.Check(sal_False);
256                 m_pTableControl->enableRelation(false);
257                 ::rtl::OUString sEmpty;
258                 m_pConnData->AppendConnLine(sEmpty,sEmpty);
259                 aPB_OK.Enable(sal_True);
260             }
261             break;
262 	}
263 
264     m_pJoinControl->m_aCBNatural.Enable(eJoinType != CROSS_JOIN);
265 
266     if ( eJoinType != eOldJoinType && eOldJoinType == CROSS_JOIN )
267     {
268         m_pConnData->ResetConnLines();
269     }
270     if ( eJoinType != CROSS_JOIN )
271     {
272         m_pTableControl->NotifyCellChange();
273         NaturalToggleHdl(&m_pJoinControl->m_aCBNatural);
274     }
275 
276     m_pTableControl->Invalidate();
277 
278 	String sHelpText = String( ModuleRes( nResId ) );
279 	if( nPos )
280 	{
281 		sHelpText.SearchAndReplace( String( RTL_CONSTASCII_STRINGPARAM( "%1" ) ), sFirstWinName );
282 		sHelpText.SearchAndReplace( String( RTL_CONSTASCII_STRINGPARAM( "%2" ) ), sSecondWinName );
283 	}
284     if ( bAddHint )
285     {
286         sHelpText += String( RTL_CONSTASCII_STRINGPARAM( "\n" ) );
287         sHelpText += String( ModuleRes( STR_JOIN_TYPE_HINT ) );
288     }
289 
290     aML_HelpText.SetText( sHelpText );
291 	return 1;
292 }
293 // -----------------------------------------------------------------------------
294 
295 IMPL_LINK( DlgQryJoin, OKClickHdl, Button*, /*pButton*/ )
296 {
297 	DBG_CHKTHIS(DlgQryJoin,NULL);
298 
299 	m_pConnData->Update();
300 	m_pOrigConnData->CopyFrom( *m_pConnData );
301 
302 	EndDialog(RET_OK);
303 	return 1;
304 }
305 // -----------------------------------------------------------------------------
306 
307 IMPL_LINK( DlgQryJoin, NaturalToggleHdl, CheckBox*, /*pButton*/ )
308 {
309 	DBG_CHKTHIS(DlgQryJoin,NULL);
310     sal_Bool bChecked = m_pJoinControl->m_aCBNatural.IsChecked();
311     static_cast<OQueryTableConnectionData*>(m_pConnData.get())->setNatural(bChecked);
312     m_pTableControl->enableRelation(!bChecked);
313     if ( bChecked )
314     {
315         m_pConnData->ResetConnLines();
316         try
317         {
318             Reference<XNameAccess> xReferencedTableColumns(m_pConnData->getReferencedTable()->getColumns());
319             Sequence< ::rtl::OUString> aSeq = m_pConnData->getReferencingTable()->getColumns()->getElementNames();
320             const ::rtl::OUString* pIter = aSeq.getConstArray();
321             const ::rtl::OUString* pEnd	  = pIter + aSeq.getLength();
322             for(;pIter != pEnd;++pIter)
323             {
324                 if ( xReferencedTableColumns->hasByName(*pIter) )
325                     m_pConnData->AppendConnLine(*pIter,*pIter);
326             }
327         }
328         catch( const Exception& )
329         {
330             DBG_UNHANDLED_EXCEPTION();
331         }
332         m_pTableControl->NotifyCellChange();
333         m_pTableControl->Invalidate();
334     }
335 
336 	return 1;
337 }
338 // -----------------------------------------------------------------------------
339 TTableConnectionData::value_type DlgQryJoin::getConnectionData() const
340 {
341 	return m_pConnData;
342 }
343 // -----------------------------------------------------------------------------
344 void DlgQryJoin::setValid(sal_Bool _bValid)
345 {
346 	//LBChangeHdl(&aLB_JoinType);
347 
348 	aPB_OK.Enable(_bValid || eJoinType == CROSS_JOIN );
349 }
350 // -----------------------------------------------------------------------------
351 void DlgQryJoin::notifyConnectionChange( )
352 {
353 	setJoinType( static_cast<OQueryTableConnectionData*>(m_pConnData.get())->GetJoinType() );
354     m_pJoinControl->m_aCBNatural.Check(static_cast<OQueryTableConnectionData*>(m_pConnData.get())->isNatural());
355     NaturalToggleHdl(&m_pJoinControl->m_aCBNatural);
356 }
357 // -----------------------------------------------------------------------------
358 void DlgQryJoin::setJoinType(EJoinType _eNewJoinType)
359 {
360 	eJoinType = _eNewJoinType;
361     m_pJoinControl->m_aCBNatural.Enable(eJoinType != CROSS_JOIN);
362 
363     long nJoinType = 0;
364     switch ( eJoinType )
365 	{
366 		default:
367 		case INNER_JOIN:
368 			nJoinType = ID_INNER_JOIN;
369 			break;
370 		case LEFT_JOIN:
371             nJoinType = ID_LEFT_JOIN;
372 			break;
373         case RIGHT_JOIN:
374 			nJoinType = ID_RIGHT_JOIN;
375 			break;
376 		case FULL_JOIN:
377 			nJoinType = ID_FULL_JOIN;
378 			break;
379         case CROSS_JOIN:
380             nJoinType = ID_CROSS_JOIN;
381             break;
382 	}
383 
384     const sal_uInt16 nCount = m_pJoinControl->aLB_JoinType.GetEntryCount();
385     for (sal_uInt16 i = 0; i < nCount; ++i)
386     {
387         if ( nJoinType == reinterpret_cast<long>(m_pJoinControl->aLB_JoinType.GetEntryData(i)) )
388         {
389             m_pJoinControl->aLB_JoinType.SelectEntryPos(i);
390             break;
391         }
392     }
393 
394 	LBChangeHdl(&m_pJoinControl->aLB_JoinType);
395 }
396 // -----------------------------------------------------------------------------
397 
398 
399 
400