xref: /trunk/main/sc/source/ui/dbgui/sfiltdlg.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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