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 31 #ifndef _DBAUI_PARAMDIALOG_HXX_ 32 #include "paramdialog.hxx" 33 #endif 34 #ifndef _DBAUI_PARAMDIALOG_HRC_ 35 #include "paramdialog.hrc" 36 #endif 37 #ifndef _DBU_DLG_HRC_ 38 #include "dbu_dlg.hrc" 39 #endif 40 #ifndef _DBAUI_COMMON_TYPES_HXX_ 41 #include "commontypes.hxx" 42 #endif 43 #ifndef _DBAUI_MODULE_DBU_HXX_ 44 #include "moduledbu.hxx" 45 #endif 46 #ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTER_HPP_ 47 #include <com/sun/star/util/XNumberFormatter.hpp> 48 #endif 49 #ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_ 50 #include <com/sun/star/sdbc/DataType.hpp> 51 #endif 52 #ifndef _CONNECTIVITY_DBTOOLS_HXX_ 53 #include <connectivity/dbtools.hxx> 54 #endif 55 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC 56 #include "dbustrings.hrc" 57 #endif 58 #ifndef _SV_SVAPP_HXX 59 #include <vcl/svapp.hxx> 60 #endif 61 #ifndef _SV_MSGBOX_HXX 62 #include <vcl/msgbox.hxx> 63 #endif 64 #ifndef _TOOLS_DEBUG_HXX 65 #include <tools/debug.hxx> 66 #endif 67 #include <tools/diagnose_ex.h> 68 #ifndef _DBAUI_LOCALRESACCESS_HXX_ 69 #include "localresaccess.hxx" 70 #endif 71 #ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX 72 #include <unotools/syslocale.hxx> 73 #endif 74 75 #define EF_VISITED 0x0001 76 #define EF_DIRTY 0x0002 77 78 //......................................................................... 79 namespace dbaui 80 { 81 //......................................................................... 82 83 using namespace ::com::sun::star::uno; 84 using namespace ::com::sun::star::lang; 85 using namespace ::com::sun::star::beans; 86 using namespace ::com::sun::star::container; 87 using namespace ::com::sun::star::sdbc; 88 using namespace ::com::sun::star::util; 89 using namespace ::connectivity; 90 91 //================================================================== 92 //= OParameterDialog 93 //================================================================== 94 95 //------------------------------------------------------------------------------ 96 #define INIT_MEMBERS() \ 97 :ModalDialog( pParent, ModuleRes(DLG_PARAMETERS)) \ 98 ,m_aNamesFrame (this, ModuleRes(FL_PARAMS)) \ 99 ,m_aAllParams (this, ModuleRes(LB_ALLPARAMS)) \ 100 ,m_aValueFrame (this, ModuleRes(FT_VALUE)) \ 101 ,m_aParam (this, ModuleRes(ET_PARAM)) \ 102 ,m_aTravelNext (this, ModuleRes(BT_TRAVELNEXT)) \ 103 ,m_aOKBtn (this, ModuleRes(BT_OK)) \ 104 ,m_aCancelBtn (this, ModuleRes(BT_CANCEL)) \ 105 ,m_nCurrentlySelected(LISTBOX_ENTRY_NOTFOUND) \ 106 ,m_xConnection(_rxConnection) \ 107 ,m_aPredicateInput( _rxORB, _rxConnection, getParseContext() ) \ 108 ,m_bNeedErrorOnCurrent(sal_True) \ 109 110 111 //------------------------------------------------------------------------------ 112 DBG_NAME(OParameterDialog) 113 114 OParameterDialog::OParameterDialog( 115 Window* pParent, const Reference< XIndexAccess > & rParamContainer, 116 const Reference< XConnection > & _rxConnection, const Reference< XMultiServiceFactory >& _rxORB) 117 INIT_MEMBERS() 118 { 119 DBG_CTOR(OParameterDialog,NULL); 120 121 if (_rxORB.is()) 122 m_xFormatter = Reference< XNumberFormatter>(_rxORB->createInstance( 123 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.NumberFormatter"))), UNO_QUERY); 124 else { 125 DBG_ERROR("OParameterDialog::OParameterDialog: need a service factory!"); 126 } 127 128 Reference< XNumberFormatsSupplier > xNumberFormats = ::dbtools::getNumberFormats(m_xConnection, sal_True); 129 if (!xNumberFormats.is()) 130 ::comphelper::disposeComponent(m_xFormatter); 131 else if (m_xFormatter.is()) 132 m_xFormatter->attachNumberFormatsSupplier(xNumberFormats); 133 try 134 { 135 DBG_ASSERT(rParamContainer->getCount(), "OParameterDialog::OParameterDialog : can't handle empty containers !"); 136 137 m_aFinalValues.realloc(rParamContainer->getCount()); 138 PropertyValue* pValues = m_aFinalValues.getArray(); 139 140 for (sal_Int32 i = 0, nCount = rParamContainer->getCount(); i<nCount; ++i, ++pValues) 141 { 142 Reference< XPropertySet > xParamAsSet; 143 rParamContainer->getByIndex(i) >>= xParamAsSet; 144 OSL_ENSURE(xParamAsSet.is(),"Parameter is null!"); 145 if(!xParamAsSet.is()) 146 continue; 147 pValues->Name = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME)); 148 m_aAllParams.InsertEntry(pValues->Name); 149 150 if (!pValues->Value.hasValue()) 151 // it won't have a value, 'cause it's default constructed. But may be later we support 152 // initializing this dialog with values 153 pValues->Value = makeAny(::rtl::OUString()); 154 // default the values to an empty string 155 156 m_aVisitedParams.push_back(0); 157 // not visited, not dirty 158 } 159 160 m_xParams = rParamContainer; 161 } 162 catch(Exception&) 163 { 164 DBG_UNHANDLED_EXCEPTION(); 165 } 166 167 168 Construct(); 169 170 m_aResetVisitFlag.SetTimeoutHdl(LINK(this, OParameterDialog, OnVisitedTimeout)); 171 172 FreeResource(); 173 } 174 175 //------------------------------------------------------------------------------ 176 OParameterDialog::~OParameterDialog() 177 { 178 if (m_aResetVisitFlag.IsActive()) 179 m_aResetVisitFlag.Stop(); 180 181 DBG_DTOR(OParameterDialog,NULL); 182 } 183 184 //------------------------------------------------------------------------------ 185 void OParameterDialog::Construct() 186 { 187 m_aAllParams.SetSelectHdl(LINK(this, OParameterDialog, OnEntrySelected)); 188 m_aParam.SetLoseFocusHdl(LINK(this, OParameterDialog, OnValueLoseFocus)); 189 m_aParam.SetModifyHdl(LINK(this, OParameterDialog, OnValueModified)); 190 m_aTravelNext.SetClickHdl(LINK(this, OParameterDialog, OnButtonClicked)); 191 m_aOKBtn.SetClickHdl(LINK(this, OParameterDialog, OnButtonClicked)); 192 m_aCancelBtn.SetClickHdl(LINK(this, OParameterDialog, OnButtonClicked)); 193 194 if (m_aAllParams.GetEntryCount()) 195 { 196 m_aAllParams.SelectEntryPos(0); 197 LINK(this, OParameterDialog, OnEntrySelected).Call(&m_aAllParams); 198 199 if (m_aAllParams.GetEntryCount() == 1) 200 { 201 m_aTravelNext.Enable(sal_False); 202 } 203 204 if (m_aAllParams.GetEntryCount() > 1) 205 { 206 m_aOKBtn.SetStyle(m_aOKBtn.GetStyle() & ~WB_DEFBUTTON); 207 m_aTravelNext.SetStyle(m_aTravelNext.GetStyle() | WB_DEFBUTTON); 208 } 209 } 210 211 m_aParam.GrabFocus(); 212 } 213 214 //------------------------------------------------------------------------------ 215 IMPL_LINK(OParameterDialog, OnValueLoseFocus, Control*, /*pSource*/) 216 { 217 if (m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND) 218 { 219 if ( ( m_aVisitedParams[ m_nCurrentlySelected ] & EF_DIRTY ) == 0 ) 220 // nothing to do, the value isn't dirty 221 return 0L; 222 } 223 224 // transform the current string according to the param field type 225 ::rtl::OUString sTransformedText(m_aParam.GetText()); 226 Reference< XPropertySet > xParamAsSet; 227 m_xParams->getByIndex(m_nCurrentlySelected) >>= xParamAsSet; 228 if (xParamAsSet.is()) 229 { 230 if (m_xConnection.is() && m_xFormatter.is()) 231 { 232 ::rtl::OUString sParamValue( m_aParam.GetText() ); 233 sal_Bool bValid = m_aPredicateInput.normalizePredicateString( sParamValue, xParamAsSet ); 234 m_aParam.SetText( sParamValue ); 235 if ( bValid ) 236 { 237 // with this the value isn't dirty anymore 238 if (m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND) 239 m_aVisitedParams[m_nCurrentlySelected] &= ~EF_DIRTY; 240 } 241 else 242 { 243 if (!m_bNeedErrorOnCurrent) 244 return 1L; 245 246 m_bNeedErrorOnCurrent = sal_False; // will be reset in OnValueModified 247 248 ::rtl::OUString sName; 249 try 250 { 251 sName = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME)); 252 } 253 catch(Exception&) 254 { 255 DBG_UNHANDLED_EXCEPTION(); 256 } 257 258 String sMessage; 259 { 260 LocalResourceAccess aDummy(DLG_PARAMETERS, RSC_MODALDIALOG); 261 sMessage = String(ModuleRes(STR_COULD_NOT_CONVERT_PARAM)); 262 } 263 sMessage.SearchAndReplaceAll(String::CreateFromAscii("$name$"), sName.getStr()); 264 ErrorBox(NULL, WB_OK, sMessage).Execute(); 265 m_aParam.GrabFocus(); 266 return 1L; 267 } 268 } 269 } 270 271 return 0L; 272 } 273 274 //------------------------------------------------------------------------------ 275 IMPL_LINK(OParameterDialog, OnButtonClicked, PushButton*, pButton) 276 { 277 if (&m_aCancelBtn == pButton) 278 { 279 // no interpreting of the given values anymore .... 280 m_aParam.SetLoseFocusHdl(Link()); // no direct call from the control anymore ... 281 m_bNeedErrorOnCurrent = sal_False; // in case of any indirect calls -> no error message 282 m_aCancelBtn.SetClickHdl(Link()); 283 m_aCancelBtn.Click(); 284 } 285 else if (&m_aOKBtn == pButton) 286 { 287 // transfer the current values into the Any 288 if (LINK(this, OParameterDialog, OnEntrySelected).Call(&m_aAllParams) != 0L) 289 { // there was an error interpreting the current text 290 m_bNeedErrorOnCurrent = sal_True; 291 // we're are out of the complex web :) of direct and indirect calls to OnValueLoseFocus now, 292 // so the next time it is called we need an error message, again .... 293 // (TODO : there surely are better solutions for this ...) 294 return 1L; 295 } 296 297 if (m_xParams.is()) 298 { 299 // write the parameters 300 try 301 { 302 ::rtl::OUString sError; 303 PropertyValue* pValues = m_aFinalValues.getArray(); 304 for (sal_Int32 i = 0, nCount = m_xParams->getCount(); i<nCount; ++i, ++pValues) 305 { 306 Reference< XPropertySet > xParamAsSet; 307 m_xParams->getByIndex(i) >>= xParamAsSet; 308 309 ::rtl::OUString sValue; 310 pValues->Value >>= sValue; 311 pValues->Value <<= ::rtl::OUString( m_aPredicateInput.getPredicateValue( sValue, xParamAsSet, sal_False ) ); 312 } 313 } 314 catch(Exception&) 315 { 316 DBG_UNHANDLED_EXCEPTION(); 317 } 318 319 } 320 // to close the dialog (which is more code than a simple EndDialog) 321 m_aOKBtn.SetClickHdl(Link()); 322 m_aOKBtn.Click(); 323 } 324 else if (&m_aTravelNext == pButton) 325 { 326 sal_uInt16 nCurrent = m_aAllParams.GetSelectEntryPos(); 327 sal_uInt16 nCount = m_aAllParams.GetEntryCount(); 328 DBG_ASSERT(nCount == m_aVisitedParams.size(), "OParameterDialog::OnButtonClicked : inconsistent lists !"); 329 330 // search the next entry in list we haven't visited yet 331 sal_uInt16 nNext = (nCurrent + 1) % nCount; 332 while ((nNext != nCurrent) && ( m_aVisitedParams[nNext] & EF_VISITED )) 333 nNext = (nNext + 1) % nCount; 334 335 if ( m_aVisitedParams[nNext] & EF_VISITED ) 336 // there is no such "not visited yet" entry -> simpy take the next one 337 nNext = (nCurrent + 1) % nCount; 338 339 m_aAllParams.SelectEntryPos(nNext); 340 LINK(this, OParameterDialog, OnEntrySelected).Call(&m_aAllParams); 341 m_bNeedErrorOnCurrent = sal_True; 342 // we're are out of the complex web :) of direct and indirect calls to OnValueLoseFocus now, 343 // so the next time it is called we need an error message, again .... 344 // (TODO : there surely are better solutions for this ...) 345 } 346 347 return 0L; 348 } 349 350 //------------------------------------------------------------------------------ 351 IMPL_LINK(OParameterDialog, OnEntrySelected, ListBox*, /*pList*/) 352 { 353 if (m_aResetVisitFlag.IsActive()) 354 { 355 LINK(this, OParameterDialog, OnVisitedTimeout).Call(&m_aResetVisitFlag); 356 m_aResetVisitFlag.Stop(); 357 } 358 // save the old values 359 if (m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND) 360 { 361 // do the transformation of the current text 362 if (LINK(this, OParameterDialog, OnValueLoseFocus).Call(&m_aParam) != 0L) 363 { // there was an error interpreting the text 364 m_aAllParams.SelectEntryPos(m_nCurrentlySelected); 365 return 1L; 366 } 367 368 m_aFinalValues[m_nCurrentlySelected].Value <<= ::rtl::OUString(m_aParam.GetText()); 369 } 370 371 // initialize the controls with the new values 372 sal_uInt16 nSelected = m_aAllParams.GetSelectEntryPos(); 373 DBG_ASSERT(nSelected != LISTBOX_ENTRY_NOTFOUND, "OParameterDialog::OnEntrySelected : no current entry !"); 374 375 m_aParam.SetText(::comphelper::getString(m_aFinalValues[nSelected].Value)); 376 m_nCurrentlySelected = nSelected; 377 378 // with this the value isn't dirty 379 DBG_ASSERT(m_nCurrentlySelected < m_aVisitedParams.size(), "OParameterDialog::OnEntrySelected : invalid current entry !"); 380 m_aVisitedParams[m_nCurrentlySelected] &= ~EF_DIRTY; 381 382 m_aResetVisitFlag.SetTimeout(1000); 383 m_aResetVisitFlag.Start(); 384 385 return 0L; 386 } 387 388 //------------------------------------------------------------------------------ 389 IMPL_LINK(OParameterDialog, OnVisitedTimeout, Timer*, /*pTimer*/) 390 { 391 DBG_ASSERT(m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND, "OParameterDialog::OnVisitedTimeout : invalid call !"); 392 393 // mark the currently selected entry as visited 394 DBG_ASSERT(m_nCurrentlySelected < m_aVisitedParams.size(), "OParameterDialog::OnVisitedTimeout : invalid entry !"); 395 m_aVisitedParams[m_nCurrentlySelected] |= EF_VISITED; 396 397 // was it the last "not visited yet" entry ? 398 ConstByteVectorIterator aIter; 399 for ( aIter = m_aVisitedParams.begin(); 400 aIter < m_aVisitedParams.end(); 401 ++aIter 402 ) 403 { 404 if (((*aIter) & EF_VISITED) == 0) 405 break; 406 } 407 if (aIter == m_aVisitedParams.end()) 408 { // yes, there isn't another one -> change the "default button" 409 m_aTravelNext.SetStyle(m_aTravelNext.GetStyle() & ~WB_DEFBUTTON); 410 m_aOKBtn.SetStyle(m_aOKBtn.GetStyle() | WB_DEFBUTTON); 411 412 // set to focus to one of the buttons temporary (with this their "default"-state is really updated) 413 Window* pOldFocus = Application::GetFocusWindow(); 414 415 // if the old focus window is the value edit do some preparations ... 416 Selection aSel; 417 if (pOldFocus == &m_aParam) 418 { 419 m_aParam.SetLoseFocusHdl(Link()); 420 aSel = m_aParam.GetSelection(); 421 } 422 m_aTravelNext.GrabFocus(); 423 if (pOldFocus) 424 pOldFocus->GrabFocus(); 425 426 // restore the settings for the value edit 427 if (pOldFocus == &m_aParam) 428 { 429 m_aParam.SetLoseFocusHdl(LINK(this, OParameterDialog, OnValueLoseFocus)); 430 m_aParam.SetSelection(aSel); 431 } 432 } 433 434 return 0L; 435 } 436 437 //------------------------------------------------------------------------------ 438 IMPL_LINK(OParameterDialog, OnValueModified, Control*, /*pBox*/) 439 { 440 // mark the currently selected entry as dirty 441 DBG_ASSERT(m_nCurrentlySelected < m_aVisitedParams.size(), "OParameterDialog::OnValueModified : invalid entry !"); 442 m_aVisitedParams[m_nCurrentlySelected] |= EF_DIRTY; 443 444 m_bNeedErrorOnCurrent = sal_True; 445 446 return 0L; 447 } 448 449 450 //......................................................................... 451 } // namespace dbaui 452 //......................................................................... 453