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