1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "paramdialog.hxx"
31 #include "paramdialog.hrc"
32 #include "dbu_dlg.hrc"
33 #include "commontypes.hxx"
34 #include "moduledbu.hxx"
35 #include <com/sun/star/util/XNumberFormatter.hpp>
36 #include <com/sun/star/sdbc/DataType.hpp>
37 #include <connectivity/dbtools.hxx>
38 #include "dbustrings.hrc"
39 #include <vcl/svapp.hxx>
40 #include <vcl/msgbox.hxx>
41 #include <osl/diagnose.h>
42 #include <tools/diagnose_ex.h>
43 #include "localresaccess.hxx"
44 #include <unotools/syslocale.hxx>
46 #define EF_VISITED 0x0001
47 #define EF_DIRTY 0x0002
49 //.........................................................................
52 //.........................................................................
54 using namespace ::com::sun::star::uno
;
55 using namespace ::com::sun::star::lang
;
56 using namespace ::com::sun::star::beans
;
57 using namespace ::com::sun::star::container
;
58 using namespace ::com::sun::star::sdbc
;
59 using namespace ::com::sun::star::util
;
60 using namespace ::connectivity
;
62 //==================================================================
64 //==================================================================
66 //------------------------------------------------------------------------------
67 #define INIT_MEMBERS() \
68 :ModalDialog( pParent, ModuleRes(DLG_PARAMETERS)) \
69 ,m_aNamesFrame (this, ModuleRes(FL_PARAMS)) \
70 ,m_aAllParams (this, ModuleRes(LB_ALLPARAMS)) \
71 ,m_aValueFrame (this, ModuleRes(FT_VALUE)) \
72 ,m_aParam (this, ModuleRes(ET_PARAM)) \
73 ,m_aTravelNext (this, ModuleRes(BT_TRAVELNEXT)) \
74 ,m_aOKBtn (this, ModuleRes(BT_OK)) \
75 ,m_aCancelBtn (this, ModuleRes(BT_CANCEL)) \
76 ,m_nCurrentlySelected(LISTBOX_ENTRY_NOTFOUND) \
77 ,m_xConnection(_rxConnection) \
78 ,m_aPredicateInput( _rxORB, _rxConnection, getParseContext() ) \
79 ,m_bNeedErrorOnCurrent(sal_True) \
82 //------------------------------------------------------------------------------
83 DBG_NAME(OParameterDialog
)
85 OParameterDialog::OParameterDialog(
86 Window
* pParent
, const Reference
< XIndexAccess
> & rParamContainer
,
87 const Reference
< XConnection
> & _rxConnection
, const Reference
< XMultiServiceFactory
>& _rxORB
)
90 DBG_CTOR(OParameterDialog
,NULL
);
93 m_xFormatter
= Reference
< XNumberFormatter
>(_rxORB
->createInstance(
94 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.NumberFormatter"))), UNO_QUERY
);
96 OSL_FAIL("OParameterDialog::OParameterDialog: need a service factory!");
99 Reference
< XNumberFormatsSupplier
> xNumberFormats
= ::dbtools::getNumberFormats(m_xConnection
, sal_True
);
100 if (!xNumberFormats
.is())
101 ::comphelper::disposeComponent(m_xFormatter
);
102 else if (m_xFormatter
.is())
103 m_xFormatter
->attachNumberFormatsSupplier(xNumberFormats
);
106 OSL_ENSURE(rParamContainer
->getCount(), "OParameterDialog::OParameterDialog : can't handle empty containers !");
108 m_aFinalValues
.realloc(rParamContainer
->getCount());
109 PropertyValue
* pValues
= m_aFinalValues
.getArray();
111 for (sal_Int32 i
= 0, nCount
= rParamContainer
->getCount(); i
<nCount
; ++i
, ++pValues
)
113 Reference
< XPropertySet
> xParamAsSet
;
114 rParamContainer
->getByIndex(i
) >>= xParamAsSet
;
115 OSL_ENSURE(xParamAsSet
.is(),"Parameter is null!");
116 if(!xParamAsSet
.is())
118 pValues
->Name
= ::comphelper::getString(xParamAsSet
->getPropertyValue(PROPERTY_NAME
));
119 m_aAllParams
.InsertEntry(pValues
->Name
);
121 if (!pValues
->Value
.hasValue())
122 // it won't have a value, 'cause it's default constructed. But may be later we support
123 // initializing this dialog with values
124 pValues
->Value
= makeAny(::rtl::OUString());
125 // default the values to an empty string
127 m_aVisitedParams
.push_back(0);
128 // not visited, not dirty
131 m_xParams
= rParamContainer
;
135 DBG_UNHANDLED_EXCEPTION();
141 m_aResetVisitFlag
.SetTimeoutHdl(LINK(this, OParameterDialog
, OnVisitedTimeout
));
146 //------------------------------------------------------------------------------
147 OParameterDialog::~OParameterDialog()
149 if (m_aResetVisitFlag
.IsActive())
150 m_aResetVisitFlag
.Stop();
152 DBG_DTOR(OParameterDialog
,NULL
);
155 //------------------------------------------------------------------------------
156 void OParameterDialog::Construct()
158 m_aAllParams
.SetSelectHdl(LINK(this, OParameterDialog
, OnEntrySelected
));
159 m_aParam
.SetLoseFocusHdl(LINK(this, OParameterDialog
, OnValueLoseFocus
));
160 m_aParam
.SetModifyHdl(LINK(this, OParameterDialog
, OnValueModified
));
161 m_aTravelNext
.SetClickHdl(LINK(this, OParameterDialog
, OnButtonClicked
));
162 m_aOKBtn
.SetClickHdl(LINK(this, OParameterDialog
, OnButtonClicked
));
163 m_aCancelBtn
.SetClickHdl(LINK(this, OParameterDialog
, OnButtonClicked
));
165 if (m_aAllParams
.GetEntryCount())
167 m_aAllParams
.SelectEntryPos(0);
168 LINK(this, OParameterDialog
, OnEntrySelected
).Call(&m_aAllParams
);
170 if (m_aAllParams
.GetEntryCount() == 1)
172 m_aTravelNext
.Enable(sal_False
);
175 if (m_aAllParams
.GetEntryCount() > 1)
177 m_aOKBtn
.SetStyle(m_aOKBtn
.GetStyle() & ~WB_DEFBUTTON
);
178 m_aTravelNext
.SetStyle(m_aTravelNext
.GetStyle() | WB_DEFBUTTON
);
182 m_aParam
.GrabFocus();
185 //------------------------------------------------------------------------------
186 IMPL_LINK(OParameterDialog
, OnValueLoseFocus
, Control
*, /*pSource*/)
188 if (m_nCurrentlySelected
!= LISTBOX_ENTRY_NOTFOUND
)
190 if ( ( m_aVisitedParams
[ m_nCurrentlySelected
] & EF_DIRTY
) == 0 )
191 // nothing to do, the value isn't dirty
195 // transform the current string according to the param field type
196 ::rtl::OUString
sTransformedText(m_aParam
.GetText());
197 Reference
< XPropertySet
> xParamAsSet
;
198 m_xParams
->getByIndex(m_nCurrentlySelected
) >>= xParamAsSet
;
199 if (xParamAsSet
.is())
201 if (m_xConnection
.is() && m_xFormatter
.is())
203 ::rtl::OUString
sParamValue( m_aParam
.GetText() );
204 sal_Bool bValid
= m_aPredicateInput
.normalizePredicateString( sParamValue
, xParamAsSet
);
205 m_aParam
.SetText( sParamValue
);
208 // with this the value isn't dirty anymore
209 if (m_nCurrentlySelected
!= LISTBOX_ENTRY_NOTFOUND
)
210 m_aVisitedParams
[m_nCurrentlySelected
] &= ~EF_DIRTY
;
214 if (!m_bNeedErrorOnCurrent
)
217 m_bNeedErrorOnCurrent
= sal_False
; // will be reset in OnValueModified
219 ::rtl::OUString sName
;
222 sName
= ::comphelper::getString(xParamAsSet
->getPropertyValue(PROPERTY_NAME
));
226 DBG_UNHANDLED_EXCEPTION();
231 LocalResourceAccess
aDummy(DLG_PARAMETERS
, RSC_MODALDIALOG
);
232 sMessage
= String(ModuleRes(STR_COULD_NOT_CONVERT_PARAM
));
234 sMessage
.SearchAndReplaceAll(String::CreateFromAscii("$name$"), sName
.getStr());
235 ErrorBox(NULL
, WB_OK
, sMessage
).Execute();
236 m_aParam
.GrabFocus();
245 //------------------------------------------------------------------------------
246 IMPL_LINK(OParameterDialog
, OnButtonClicked
, PushButton
*, pButton
)
248 if (&m_aCancelBtn
== pButton
)
250 // no interpreting of the given values anymore ....
251 m_aParam
.SetLoseFocusHdl(Link()); // no direct call from the control anymore ...
252 m_bNeedErrorOnCurrent
= sal_False
; // in case of any indirect calls -> no error message
253 m_aCancelBtn
.SetClickHdl(Link());
254 m_aCancelBtn
.Click();
256 else if (&m_aOKBtn
== pButton
)
258 // transfer the current values into the Any
259 if (LINK(this, OParameterDialog
, OnEntrySelected
).Call(&m_aAllParams
) != 0L)
260 { // there was an error interpreting the current text
261 m_bNeedErrorOnCurrent
= sal_True
;
262 // we're are out of the complex web :) of direct and indirect calls to OnValueLoseFocus now,
263 // so the next time it is called we need an error message, again ....
264 // (TODO : there surely are better solutions for this ...)
270 // write the parameters
273 PropertyValue
* pValues
= m_aFinalValues
.getArray();
274 for (sal_Int32 i
= 0, nCount
= m_xParams
->getCount(); i
<nCount
; ++i
, ++pValues
)
276 Reference
< XPropertySet
> xParamAsSet
;
277 m_xParams
->getByIndex(i
) >>= xParamAsSet
;
279 ::rtl::OUString sValue
;
280 pValues
->Value
>>= sValue
;
281 pValues
->Value
<<= ::rtl::OUString( m_aPredicateInput
.getPredicateValue( sValue
, xParamAsSet
, sal_False
) );
286 DBG_UNHANDLED_EXCEPTION();
290 // to close the dialog (which is more code than a simple EndDialog)
291 m_aOKBtn
.SetClickHdl(Link());
294 else if (&m_aTravelNext
== pButton
)
296 sal_uInt16 nCurrent
= m_aAllParams
.GetSelectEntryPos();
297 sal_uInt16 nCount
= m_aAllParams
.GetEntryCount();
298 OSL_ENSURE(nCount
== m_aVisitedParams
.size(), "OParameterDialog::OnButtonClicked : inconsistent lists !");
300 // search the next entry in list we haven't visited yet
301 sal_uInt16 nNext
= (nCurrent
+ 1) % nCount
;
302 while ((nNext
!= nCurrent
) && ( m_aVisitedParams
[nNext
] & EF_VISITED
))
303 nNext
= (nNext
+ 1) % nCount
;
305 if ( m_aVisitedParams
[nNext
] & EF_VISITED
)
306 // there is no such "not visited yet" entry -> simpy take the next one
307 nNext
= (nCurrent
+ 1) % nCount
;
309 m_aAllParams
.SelectEntryPos(nNext
);
310 LINK(this, OParameterDialog
, OnEntrySelected
).Call(&m_aAllParams
);
311 m_bNeedErrorOnCurrent
= sal_True
;
312 // we're are out of the complex web :) of direct and indirect calls to OnValueLoseFocus now,
313 // so the next time it is called we need an error message, again ....
314 // (TODO : there surely are better solutions for this ...)
320 //------------------------------------------------------------------------------
321 IMPL_LINK(OParameterDialog
, OnEntrySelected
, ListBox
*, /*pList*/)
323 if (m_aResetVisitFlag
.IsActive())
325 LINK(this, OParameterDialog
, OnVisitedTimeout
).Call(&m_aResetVisitFlag
);
326 m_aResetVisitFlag
.Stop();
328 // save the old values
329 if (m_nCurrentlySelected
!= LISTBOX_ENTRY_NOTFOUND
)
331 // do the transformation of the current text
332 if (LINK(this, OParameterDialog
, OnValueLoseFocus
).Call(&m_aParam
) != 0L)
333 { // there was an error interpreting the text
334 m_aAllParams
.SelectEntryPos(m_nCurrentlySelected
);
338 m_aFinalValues
[m_nCurrentlySelected
].Value
<<= ::rtl::OUString(m_aParam
.GetText());
341 // initialize the controls with the new values
342 sal_uInt16 nSelected
= m_aAllParams
.GetSelectEntryPos();
343 OSL_ENSURE(nSelected
!= LISTBOX_ENTRY_NOTFOUND
, "OParameterDialog::OnEntrySelected : no current entry !");
345 m_aParam
.SetText(::comphelper::getString(m_aFinalValues
[nSelected
].Value
));
346 m_nCurrentlySelected
= nSelected
;
348 // with this the value isn't dirty
349 OSL_ENSURE(m_nCurrentlySelected
< m_aVisitedParams
.size(), "OParameterDialog::OnEntrySelected : invalid current entry !");
350 m_aVisitedParams
[m_nCurrentlySelected
] &= ~EF_DIRTY
;
352 m_aResetVisitFlag
.SetTimeout(1000);
353 m_aResetVisitFlag
.Start();
358 //------------------------------------------------------------------------------
359 IMPL_LINK(OParameterDialog
, OnVisitedTimeout
, Timer
*, /*pTimer*/)
361 OSL_ENSURE(m_nCurrentlySelected
!= LISTBOX_ENTRY_NOTFOUND
, "OParameterDialog::OnVisitedTimeout : invalid call !");
363 // mark the currently selected entry as visited
364 OSL_ENSURE(m_nCurrentlySelected
< m_aVisitedParams
.size(), "OParameterDialog::OnVisitedTimeout : invalid entry !");
365 m_aVisitedParams
[m_nCurrentlySelected
] |= EF_VISITED
;
367 // was it the last "not visited yet" entry ?
368 ConstByteVectorIterator aIter
;
369 for ( aIter
= m_aVisitedParams
.begin();
370 aIter
< m_aVisitedParams
.end();
374 if (((*aIter
) & EF_VISITED
) == 0)
377 if (aIter
== m_aVisitedParams
.end())
378 { // yes, there isn't another one -> change the "default button"
379 m_aTravelNext
.SetStyle(m_aTravelNext
.GetStyle() & ~WB_DEFBUTTON
);
380 m_aOKBtn
.SetStyle(m_aOKBtn
.GetStyle() | WB_DEFBUTTON
);
382 // set to focus to one of the buttons temporary (with this their "default"-state is really updated)
383 Window
* pOldFocus
= Application::GetFocusWindow();
385 // if the old focus window is the value edit do some preparations ...
387 if (pOldFocus
== &m_aParam
)
389 m_aParam
.SetLoseFocusHdl(Link());
390 aSel
= m_aParam
.GetSelection();
392 m_aTravelNext
.GrabFocus();
394 pOldFocus
->GrabFocus();
396 // restore the settings for the value edit
397 if (pOldFocus
== &m_aParam
)
399 m_aParam
.SetLoseFocusHdl(LINK(this, OParameterDialog
, OnValueLoseFocus
));
400 m_aParam
.SetSelection(aSel
);
407 //------------------------------------------------------------------------------
408 IMPL_LINK(OParameterDialog
, OnValueModified
, Control
*, /*pBox*/)
410 // mark the currently selected entry as dirty
411 OSL_ENSURE(m_nCurrentlySelected
< m_aVisitedParams
.size(), "OParameterDialog::OnValueModified : invalid entry !");
412 m_aVisitedParams
[m_nCurrentlySelected
] |= EF_DIRTY
;
414 m_bNeedErrorOnCurrent
= sal_True
;
420 //.........................................................................
422 //.........................................................................
424 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */