xref: /aoo41x/main/sc/source/ui/dbgui/sfiltdlg.cxx (revision cdf0e10c)
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_sc.hxx"
30 
31 // System - Includes ---------------------------------------------------------
32 
33 
34 
35 // INCLUDE -------------------------------------------------------------------
36 #include <sfx2/dispatch.hxx>
37 
38 #include "uiitems.hxx"
39 #include "rangenam.hxx"
40 #include "dbcolect.hxx"
41 #include "reffact.hxx"
42 #include "viewdata.hxx"
43 #include "document.hxx"
44 #include "docsh.hxx"
45 #include "scresid.hxx"
46 
47 #include "foptmgr.hxx"
48 
49 #include "globstr.hrc"
50 #include "filter.hrc"
51 
52 #define _SFILTDLG_CXX
53 #include "filtdlg.hxx"
54 #undef _SFILTDLG_CXX
55 #include <vcl/msgbox.hxx>
56 
57 // DEFINE --------------------------------------------------------------------
58 
59 #define ERRORBOX(rid) ErrorBox( this, WinBits( WB_OK|WB_DEF_OK),\
60 				 	   			ScGlobal::GetRscString(rid) ).Execute()
61 
62 
63 //============================================================================
64 //	class ScSpecialFilterDialog
65 
66 //----------------------------------------------------------------------------
67 
68 ScSpecialFilterDlg::ScSpecialFilterDlg( SfxBindings* pB, SfxChildWindow* pCW, Window* pParent,
69 										const SfxItemSet&	rArgSet )
70 
71 	:	ScAnyRefDlg	( pB, pCW, pParent, RID_SCDLG_SPEC_FILTER ),
72 		//
73 		aFtFilterArea	( this, ScResId( FT_CRITERIA_AREA ) ),
74 		aLbFilterArea	( this, ScResId( LB_CRITERIA_AREA ) ),
75         aEdFilterArea   ( this, this, ScResId( ED_CRITERIA_AREA ) ),
76 		aRbFilterArea	( this, ScResId( RB_CRITERIA_AREA ), &aEdFilterArea, this ),
77 		//
78         aFlOptions      ( this, ScResId( FL_OPTIONS ) ),
79 		_INIT_COMMON_FILTER_RSCOBJS
80         aBtnOk          ( this, ScResId( BTN_OK ) ),
81         aBtnCancel      ( this, ScResId( BTN_CANCEL ) ),
82         aBtnHelp        ( this, ScResId( BTN_HELP ) ),
83         aBtnMore        ( this, ScResId( BTN_MORE ) ),
84 		//
85 		pOptionsMgr		( NULL ),
86 		nWhichQuery		( rArgSet.GetPool()->GetWhich( SID_QUERY ) ),
87 		theQueryData	( ((const ScQueryItem&)
88 						   rArgSet.Get( nWhichQuery )).GetQueryData() ),
89 		pOutItem		( NULL ),
90 		pViewData		( NULL ),
91 		pDoc			( NULL ),
92 		pRefInputEdit	( NULL ),
93 		bRefInputMode	( sal_False ),
94 		pTimer			( NULL )
95 {
96 	Init( rArgSet );
97 	aEdFilterArea.GrabFocus();
98 
99 	FreeResource();
100 
101 	// Hack: RefInput-Kontrolle
102 	pTimer = new Timer;
103 	pTimer->SetTimeout( 50 ); // 50ms warten
104 	pTimer->SetTimeoutHdl( LINK( this, ScSpecialFilterDlg, TimeOutHdl ) );
105 	pTimer->Start();
106 
107 	aLbCopyArea.SetAccessibleName(aBtnCopyResult.GetText());
108 	aEdCopyArea.SetAccessibleName(aBtnCopyResult.GetText());
109 	aLbCopyArea.SetAccessibleRelationLabeledBy(&aBtnCopyResult);
110 	aEdCopyArea.SetAccessibleRelationLabeledBy(&aBtnCopyResult);
111 }
112 
113 
114 //----------------------------------------------------------------------------
115 
116 __EXPORT ScSpecialFilterDlg::~ScSpecialFilterDlg()
117 {
118 	sal_uInt16 nEntries = aLbFilterArea.GetEntryCount();
119 	sal_uInt16 i;
120 
121 	for ( i=1; i<nEntries; i++ )
122 		delete (String*)aLbFilterArea.GetEntryData( i );
123 
124 	delete pOptionsMgr;
125 
126 	if ( pOutItem )
127 		delete pOutItem;
128 
129 	// Hack: RefInput-Kontrolle
130 	pTimer->Stop();
131 	delete pTimer;
132 }
133 
134 
135 //----------------------------------------------------------------------------
136 
137 void __EXPORT ScSpecialFilterDlg::Init( const SfxItemSet& rArgSet )
138 {
139 	const ScQueryItem& rQueryItem = (const ScQueryItem&)
140 									rArgSet.Get( nWhichQuery );
141 
142 	aBtnOk.SetClickHdl			( LINK( this, ScSpecialFilterDlg, EndDlgHdl ) );
143 	aBtnCancel.SetClickHdl		( LINK( this, ScSpecialFilterDlg, EndDlgHdl ) );
144 	aLbFilterArea.SetSelectHdl	( LINK( this, ScSpecialFilterDlg, FilterAreaSelHdl ) );
145 	aEdFilterArea.SetModifyHdl	( LINK( this, ScSpecialFilterDlg, FilterAreaModHdl ) );
146 
147 	pViewData 	= rQueryItem.GetViewData();
148 	pDoc	  	= pViewData ? pViewData->GetDocument()  : NULL;
149 
150 	aEdFilterArea.SetText( EMPTY_STRING );		// may be overwritten below
151 
152 	if ( pViewData && pDoc )
153 	{
154 		if(pDoc->GetChangeTrack()!=NULL) aBtnCopyResult.Disable();
155 
156 		ScRangeName*	pRangeNames	= pDoc->GetRangeName();
157 		const sal_uInt16	nCount 		= pRangeNames ? pRangeNames->GetCount() : 0;
158 
159 		/*
160 		 * Aus den RangeNames des Dokumentes werden nun die
161 		 * gemerkt, bei denen es sich um Filter-Bereiche handelt
162 		 */
163 
164 		aLbFilterArea.Clear();
165 		aLbFilterArea.InsertEntry( aStrUndefined, 0 );
166 
167 		if ( nCount > 0 )
168 		{
169 			String		 aString;
170 			ScRangeData* pData = NULL;
171 			sal_uInt16		 nInsert = 0;
172 
173 			for ( sal_uInt16 i=0; i<nCount; i++ )
174 			{
175 				pData = (ScRangeData*)(pRangeNames->At( i ));
176 				if ( pData )
177 				{
178 					if ( pData->HasType( RT_CRITERIA ) )
179 					{
180 						pData->GetName( aString );
181 						nInsert = aLbFilterArea.InsertEntry( aString );
182 						pData->GetSymbol( aString );
183 						aLbFilterArea.SetEntryData( nInsert,
184 													new String( aString ) );
185 					}
186 				}
187 			}
188 		}
189 
190 		//	is there a stored source range?
191 
192 		ScRange aAdvSource;
193 		if (rQueryItem.GetAdvancedQuerySource(aAdvSource))
194 		{
195 			String aRefStr;
196 			aAdvSource.Format( aRefStr, SCR_ABS_3D, pDoc, pDoc->GetAddressConvention() );
197 			aEdFilterArea.SetRefString( aRefStr );
198 		}
199 	}
200 
201 	aLbFilterArea.SelectEntryPos( 0 );
202 
203 	// Optionen initialisieren lassen:
204 
205 	pOptionsMgr	 = new ScFilterOptionsMgr(
206 							this,
207 							pViewData,
208 							theQueryData,
209 							aBtnMore,
210 							aBtnCase,
211 							aBtnRegExp,
212 							aBtnHeader,
213 							aBtnUnique,
214 							aBtnCopyResult,
215 							aBtnDestPers,
216 							aLbCopyArea,
217 							aEdCopyArea,
218 							aRbCopyArea,
219 							aFtDbAreaLabel,
220 							aFtDbArea,
221                             aFlOptions,
222 							aStrNoName,
223 							aStrUndefined );
224 
225 	//	#35206# Spezialfilter braucht immer Spaltenkoepfe
226 	aBtnHeader.Check(sal_True);
227 	aBtnHeader.Disable();
228 
229 	// Modal-Modus einschalten
230 //	SetDispatcherLock( sal_True );
231 	//@BugID 54702 Enablen/Disablen nur noch in Basisklasse
232 	//SFX_APPWINDOW->Disable(sal_False);		//! allgemeine Methode im ScAnyRefDlg
233 }
234 
235 
236 //----------------------------------------------------------------------------
237 
238 sal_Bool __EXPORT ScSpecialFilterDlg::Close()
239 {
240     if (pViewData)
241         pViewData->GetDocShell()->CancelAutoDBRange();
242 
243 	return DoClose( ScSpecialFilterDlgWrapper::GetChildWindowId() );
244 }
245 
246 
247 //----------------------------------------------------------------------------
248 // Uebergabe eines mit der Maus selektierten Tabellenbereiches, der dann als
249 // neue Selektion im Referenz-Edit angezeigt wird.
250 
251 void ScSpecialFilterDlg::SetReference( const ScRange& rRef, ScDocument* pDocP )
252 {
253 	if ( bRefInputMode && pRefInputEdit )		// Nur moeglich, wenn im Referenz-Editmodus
254 	{
255 		if ( rRef.aStart != rRef.aEnd )
256 			RefInputStart( pRefInputEdit );
257 
258 		String aRefStr;
259         const formula::FormulaGrammar::AddressConvention eConv = pDocP->GetAddressConvention();
260 
261 		if ( pRefInputEdit == &aEdCopyArea)
262 			rRef.aStart.Format( aRefStr, SCA_ABS_3D, pDocP, eConv );
263 		else if ( pRefInputEdit == &aEdFilterArea)
264 			rRef.Format( aRefStr, SCR_ABS_3D, pDocP, eConv );
265 
266 		pRefInputEdit->SetRefString( aRefStr );
267 	}
268 }
269 
270 
271 //----------------------------------------------------------------------------
272 
273 void ScSpecialFilterDlg::SetActive()
274 {
275 	if ( bRefInputMode )
276 	{
277 		if ( pRefInputEdit == &aEdCopyArea )
278 		{
279 			aEdCopyArea.GrabFocus();
280 			if ( aEdCopyArea.GetModifyHdl().IsSet() )
281 				((Link&)aEdCopyArea.GetModifyHdl()).Call( &aEdCopyArea );
282 		}
283 		else if ( pRefInputEdit == &aEdFilterArea )
284 		{
285 			aEdFilterArea.GrabFocus();
286 			FilterAreaModHdl( &aEdFilterArea );
287 		}
288 	}
289 	else
290 		GrabFocus();
291 
292 	RefInputDone();
293 }
294 
295 
296 //----------------------------------------------------------------------------
297 
298 ScQueryItem* ScSpecialFilterDlg::GetOutputItem( const ScQueryParam& rParam,
299 												const ScRange& rSource )
300 {
301 	if ( pOutItem ) DELETEZ( pOutItem );
302 	pOutItem = new ScQueryItem( nWhichQuery, &rParam );
303 	pOutItem->SetAdvancedQuerySource( &rSource );
304 
305 	return pOutItem;
306 }
307 
308 
309 //----------------------------------------------------------------------------
310 
311 sal_Bool ScSpecialFilterDlg::IsRefInputMode() const
312 {
313 	return bRefInputMode;
314 }
315 
316 
317 //----------------------------------------------------------------------------
318 // Handler:
319 // ========
320 
321 IMPL_LINK( ScSpecialFilterDlg, EndDlgHdl, Button*, pBtn )
322 {
323 	DBG_ASSERT( pDoc && pViewData, "Document or ViewData not found. :-/" );
324 
325 	if ( (pBtn == &aBtnOk) && pDoc && pViewData )
326 	{
327 		String			theCopyStr( aEdCopyArea.GetText() );
328 		String			theAreaStr( aEdFilterArea.GetText() );
329 		ScQueryParam	theOutParam( theQueryData );
330 		ScAddress		theAdrCopy;
331 		sal_Bool			bEditInputOk	= sal_True;
332 		sal_Bool			bQueryOk		= sal_False;
333 		ScRange			theFilterArea;
334         const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
335 
336 		if ( aBtnCopyResult.IsChecked() )
337 		{
338 			xub_StrLen nColonPos = theCopyStr.Search( ':' );
339 
340 			if ( STRING_NOTFOUND != nColonPos )
341 				theCopyStr.Erase( nColonPos );
342 
343 			sal_uInt16 nResult = theAdrCopy.Parse( theCopyStr, pDoc, eConv );
344 
345 			if ( SCA_VALID != (nResult & SCA_VALID) )
346 			{
347 				if ( !aBtnMore.GetState() )
348 					aBtnMore.SetState( sal_True );
349 
350 				ERRORBOX( STR_INVALID_TABREF );
351 				aEdCopyArea.GrabFocus();
352 				bEditInputOk = sal_False;
353 			}
354 		}
355 
356 		if ( bEditInputOk )
357 		{
358 			sal_uInt16 nResult = ScRange().Parse( theAreaStr, pDoc, eConv );
359 
360 			if ( SCA_VALID != (nResult & SCA_VALID) )
361 			{
362 				ERRORBOX( STR_INVALID_TABREF );
363 				aEdFilterArea.GrabFocus();
364 				bEditInputOk = sal_False;
365 			}
366 		}
367 
368 		if ( bEditInputOk )
369 		{
370 			/*
371 			 * Alle Edit-Felder enthalten gueltige Bereiche.
372 			 * Nun wird versucht aus dem Filterbereich
373 			 * ein ScQueryParam zu erzeugen:
374 			 */
375 
376 			sal_uInt16	nResult = theFilterArea.Parse( theAreaStr, pDoc, eConv );
377 
378 			if ( SCA_VALID == (nResult & SCA_VALID) )
379 			{
380 				ScAddress& rStart = theFilterArea.aStart;
381 				ScAddress& rEnd   = theFilterArea.aEnd;
382 
383 				if ( aBtnCopyResult.IsChecked() )
384 				{
385 					theOutParam.bInplace	= sal_False;
386 					theOutParam.nDestTab	= theAdrCopy.Tab();
387 					theOutParam.nDestCol	= theAdrCopy.Col();
388 					theOutParam.nDestRow	= theAdrCopy.Row();
389 				}
390 				else
391 				{
392 					theOutParam.bInplace	= sal_True;
393 					theOutParam.nDestTab	= 0;
394 					theOutParam.nDestCol	= 0;
395 					theOutParam.nDestRow	= 0;
396 				}
397 
398 				theOutParam.bHasHeader = aBtnHeader.IsChecked();
399 				theOutParam.bByRow	   = sal_True;
400 				theOutParam.bCaseSens  = aBtnCase.IsChecked();
401 				theOutParam.bRegExp	   = aBtnRegExp.IsChecked();
402 				theOutParam.bDuplicate = !aBtnUnique.IsChecked();
403 				theOutParam.bDestPers  = aBtnDestPers.IsChecked();
404 
405 				bQueryOk =
406 					pDoc->CreateQueryParam( rStart.Col(),
407 											rStart.Row(),
408 											rEnd.Col(),
409 											rEnd.Row(),
410 											rStart.Tab(),
411 											theOutParam );
412 
413 				//	an der DB-Collection koennen nur MAXQUERY Filter-Eintraege
414 				//	gespeichert werden
415 
416 				if ( bQueryOk && theOutParam.GetEntryCount() > MAXQUERY &&
417 					 theOutParam.GetEntry(MAXQUERY).bDoQuery )
418 				{
419 					bQueryOk = sal_False;		// zu viele
420 											//!	andere Fehlermeldung ??
421 				}
422 			}
423 		}
424 
425 		if ( bQueryOk )
426 		{
427 			SetDispatcherLock( sal_False );
428 			SwitchToDocument();
429 			GetBindings().GetDispatcher()->Execute( FID_FILTER_OK,
430 									  SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
431 									  GetOutputItem( theOutParam, theFilterArea ), 0L, 0L );
432 			Close();
433 		}
434 		else
435 		{
436 			ERRORBOX( STR_INVALID_QUERYAREA );
437 			aEdFilterArea.GrabFocus();
438 		}
439 	}
440 	else if ( pBtn == &aBtnCancel )
441 	{
442 		Close();
443 	}
444 	return 0;
445 }
446 
447 
448 //----------------------------------------------------------------------------
449 
450 IMPL_LINK( ScSpecialFilterDlg, TimeOutHdl, Timer*, _pTimer )
451 {
452     // alle 50ms nachschauen, ob RefInputMode noch stimmt
453 
454     if( (_pTimer == pTimer) && IsActive() )
455     {
456         if( aEdCopyArea.HasFocus() || aRbCopyArea.HasFocus() )
457         {
458             pRefInputEdit = &aEdCopyArea;
459             bRefInputMode = sal_True;
460         }
461         else if( aEdFilterArea.HasFocus() || aRbFilterArea.HasFocus() )
462         {
463             pRefInputEdit = &aEdFilterArea;
464             bRefInputMode = sal_True;
465         }
466         else if( bRefInputMode )
467         {
468             pRefInputEdit = NULL;
469             bRefInputMode = sal_False;
470         }
471     }
472 
473     pTimer->Start();
474 
475 	return 0;
476 }
477 
478 
479 //----------------------------------------------------------------------------
480 
481 IMPL_LINK( ScSpecialFilterDlg, FilterAreaSelHdl, ListBox*, pLb )
482 {
483 	if ( pLb == &aLbFilterArea )
484 	{
485 		String	aString;
486 		sal_uInt16	nSelPos = aLbFilterArea.GetSelectEntryPos();
487 
488 		if ( nSelPos > 0 )
489 			aString = *(String*)aLbFilterArea.GetEntryData( nSelPos );
490 
491 		aEdFilterArea.SetText( aString );
492 	}
493 
494 	return 0;
495 }
496 
497 
498 //----------------------------------------------------------------------------
499 
500 IMPL_LINK( ScSpecialFilterDlg, FilterAreaModHdl, formula::RefEdit*, pEd )
501 {
502 	if ( pEd == &aEdFilterArea )
503 	{
504 		if ( pDoc && pViewData )
505 		{
506 			String	theCurAreaStr = pEd->GetText();
507 			sal_uInt16	nResult	= ScRange().Parse( theCurAreaStr, pDoc );
508 
509 			if ( SCA_VALID == (nResult & SCA_VALID) )
510 			{
511 				String*	pStr	= NULL;
512 				sal_Bool	bFound	= sal_False;
513 				sal_uInt16	i		= 0;
514 				sal_uInt16	nCount	= aLbFilterArea.GetEntryCount();
515 
516 				for ( i=1; i<nCount && !bFound; i++ )
517 				{
518 					pStr = (String*)aLbFilterArea.GetEntryData( i );
519 					bFound = (theCurAreaStr == *pStr);
520 				}
521 
522 				if ( bFound )
523 					aLbFilterArea.SelectEntryPos( --i );
524 				else
525 					aLbFilterArea.SelectEntryPos( 0 );
526 			}
527 		}
528 		else
529 			aLbFilterArea.SelectEntryPos( 0 );
530 	}
531 
532 	return 0;
533 }
534 
535 
536