1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "paramdialog.hxx"
22 #include "paramdialog.hrc"
23 #include "dbu_dlg.hrc"
24 #include "commontypes.hxx"
25 #include "moduledbu.hxx"
26 #include <com/sun/star/util/NumberFormatter.hpp>
27 #include <com/sun/star/sdbc/DataType.hpp>
28 #include <comphelper/processfactory.hxx>
29 #include <connectivity/dbtools.hxx>
30 #include "dbustrings.hrc"
31 #include <vcl/svapp.hxx>
32 #include <vcl/msgbox.hxx>
33 #include <osl/diagnose.h>
34 #include <tools/diagnose_ex.h>
35 #include "localresaccess.hxx"
36 #include <unotools/syslocale.hxx>
38 #define EF_VISITED 0x0001
39 #define EF_DIRTY 0x0002
41 //.........................................................................
44 //.........................................................................
46 using namespace ::com::sun::star::uno
;
47 using namespace ::com::sun::star::lang
;
48 using namespace ::com::sun::star::beans
;
49 using namespace ::com::sun::star::container
;
50 using namespace ::com::sun::star::sdbc
;
51 using namespace ::com::sun::star::util
;
52 using namespace ::connectivity
;
54 //==================================================================
56 //==================================================================
58 //------------------------------------------------------------------------------
61 //------------------------------------------------------------------------------
62 DBG_NAME(OParameterDialog
)
64 OParameterDialog::OParameterDialog(
65 Window
* pParent
, const Reference
< XIndexAccess
> & rParamContainer
,
66 const Reference
< XConnection
> & _rxConnection
, const Reference
< XComponentContext
>& rxContext
)
67 :ModalDialog( pParent
, ModuleRes(DLG_PARAMETERS
))
68 ,m_aNamesFrame (this, ModuleRes(FL_PARAMS
))
69 ,m_aAllParams (this, ModuleRes(LB_ALLPARAMS
))
70 ,m_aValueFrame (this, ModuleRes(FT_VALUE
))
71 ,m_aParam (this, ModuleRes(ET_PARAM
))
72 ,m_aTravelNext (this, ModuleRes(BT_TRAVELNEXT
))
73 ,m_aOKBtn (this, ModuleRes(BT_OK
))
74 ,m_aCancelBtn (this, ModuleRes(BT_CANCEL
))
75 ,m_nCurrentlySelected(LISTBOX_ENTRY_NOTFOUND
)
76 ,m_xConnection(_rxConnection
)
77 ,m_aPredicateInput( rxContext
, _rxConnection
, getParseContext() )
78 ,m_bNeedErrorOnCurrent(sal_True
)
80 DBG_CTOR(OParameterDialog
,NULL
);
83 m_xFormatter
= Reference
< XNumberFormatter
>( NumberFormatter::create( rxContext
), UNO_QUERY_THROW
);
85 OSL_FAIL("OParameterDialog::OParameterDialog: need a service factory!");
88 Reference
< XNumberFormatsSupplier
> xNumberFormats
= ::dbtools::getNumberFormats(m_xConnection
, sal_True
);
89 if (!xNumberFormats
.is())
90 ::comphelper::disposeComponent(m_xFormatter
);
92 m_xFormatter
->attachNumberFormatsSupplier(xNumberFormats
);
95 OSL_ENSURE(rParamContainer
->getCount(), "OParameterDialog::OParameterDialog : can't handle empty containers !");
97 m_aFinalValues
.realloc(rParamContainer
->getCount());
98 PropertyValue
* pValues
= m_aFinalValues
.getArray();
100 for (sal_Int32 i
= 0, nCount
= rParamContainer
->getCount(); i
<nCount
; ++i
, ++pValues
)
102 Reference
< XPropertySet
> xParamAsSet
;
103 rParamContainer
->getByIndex(i
) >>= xParamAsSet
;
104 OSL_ENSURE(xParamAsSet
.is(),"Parameter is null!");
105 if(!xParamAsSet
.is())
107 pValues
->Name
= ::comphelper::getString(xParamAsSet
->getPropertyValue(PROPERTY_NAME
));
108 m_aAllParams
.InsertEntry(pValues
->Name
);
110 if (!pValues
->Value
.hasValue())
111 // it won't have a value, 'cause it's default constructed. But may be later we support
112 // initializing this dialog with values
113 pValues
->Value
= makeAny( OUString() );
114 // default the values to an empty string
116 m_aVisitedParams
.push_back(0);
117 // not visited, not dirty
120 m_xParams
= rParamContainer
;
124 DBG_UNHANDLED_EXCEPTION();
130 m_aResetVisitFlag
.SetTimeoutHdl(LINK(this, OParameterDialog
, OnVisitedTimeout
));
135 //------------------------------------------------------------------------------
136 OParameterDialog::~OParameterDialog()
138 if (m_aResetVisitFlag
.IsActive())
139 m_aResetVisitFlag
.Stop();
141 DBG_DTOR(OParameterDialog
,NULL
);
144 //------------------------------------------------------------------------------
145 void OParameterDialog::Construct()
147 m_aAllParams
.SetSelectHdl(LINK(this, OParameterDialog
, OnEntrySelected
));
148 m_aParam
.SetLoseFocusHdl(LINK(this, OParameterDialog
, OnValueLoseFocus
));
149 m_aParam
.SetModifyHdl(LINK(this, OParameterDialog
, OnValueModified
));
150 m_aTravelNext
.SetClickHdl(LINK(this, OParameterDialog
, OnButtonClicked
));
151 m_aOKBtn
.SetClickHdl(LINK(this, OParameterDialog
, OnButtonClicked
));
152 m_aCancelBtn
.SetClickHdl(LINK(this, OParameterDialog
, OnButtonClicked
));
154 if (m_aAllParams
.GetEntryCount())
156 m_aAllParams
.SelectEntryPos(0);
157 LINK(this, OParameterDialog
, OnEntrySelected
).Call(&m_aAllParams
);
159 if (m_aAllParams
.GetEntryCount() == 1)
161 m_aTravelNext
.Enable(sal_False
);
164 if (m_aAllParams
.GetEntryCount() > 1)
166 m_aOKBtn
.SetStyle(m_aOKBtn
.GetStyle() & ~WB_DEFBUTTON
);
167 m_aTravelNext
.SetStyle(m_aTravelNext
.GetStyle() | WB_DEFBUTTON
);
171 m_aParam
.GrabFocus();
174 //------------------------------------------------------------------------------
175 IMPL_LINK(OParameterDialog
, OnValueLoseFocus
, Control
*, /*pSource*/)
177 if (m_nCurrentlySelected
!= LISTBOX_ENTRY_NOTFOUND
)
179 if ( ( m_aVisitedParams
[ m_nCurrentlySelected
] & EF_DIRTY
) == 0 )
180 // nothing to do, the value isn't dirty
184 Reference
< XPropertySet
> xParamAsSet
;
185 m_xParams
->getByIndex(m_nCurrentlySelected
) >>= xParamAsSet
;
186 if (xParamAsSet
.is())
188 if (m_xConnection
.is() && m_xFormatter
.is())
190 OUString
sParamValue( m_aParam
.GetText() );
191 sal_Bool bValid
= m_aPredicateInput
.normalizePredicateString( sParamValue
, xParamAsSet
);
192 m_aParam
.SetText( sParamValue
);
195 // with this the value isn't dirty anymore
196 if (m_nCurrentlySelected
!= LISTBOX_ENTRY_NOTFOUND
)
197 m_aVisitedParams
[m_nCurrentlySelected
] &= ~EF_DIRTY
;
201 if (!m_bNeedErrorOnCurrent
)
204 m_bNeedErrorOnCurrent
= sal_False
; // will be reset in OnValueModified
209 sName
= ::comphelper::getString(xParamAsSet
->getPropertyValue(PROPERTY_NAME
));
213 DBG_UNHANDLED_EXCEPTION();
218 LocalResourceAccess
aDummy(DLG_PARAMETERS
, RSC_MODALDIALOG
);
219 sMessage
= String(ModuleRes(STR_COULD_NOT_CONVERT_PARAM
));
221 sMessage
.SearchAndReplaceAll( OUString("$name$"), sName
);
222 ErrorBox(NULL
, WB_OK
, sMessage
).Execute();
223 m_aParam
.GrabFocus();
232 //------------------------------------------------------------------------------
233 IMPL_LINK(OParameterDialog
, OnButtonClicked
, PushButton
*, pButton
)
235 if (&m_aCancelBtn
== pButton
)
237 // no interpreting of the given values anymore ....
238 m_aParam
.SetLoseFocusHdl(Link()); // no direct call from the control anymore ...
239 m_bNeedErrorOnCurrent
= sal_False
; // in case of any indirect calls -> no error message
240 m_aCancelBtn
.SetClickHdl(Link());
241 m_aCancelBtn
.Click();
243 else if (&m_aOKBtn
== pButton
)
245 // transfer the current values into the Any
246 if (LINK(this, OParameterDialog
, OnEntrySelected
).Call(&m_aAllParams
) != 0L)
247 { // there was an error interpreting the current text
248 m_bNeedErrorOnCurrent
= sal_True
;
249 // we're are out of the complex web :) of direct and indirect calls to OnValueLoseFocus now,
250 // so the next time it is called we need an error message, again ....
251 // (TODO : there surely are better solutions for this ...)
257 // write the parameters
260 PropertyValue
* pValues
= m_aFinalValues
.getArray();
261 for (sal_Int32 i
= 0, nCount
= m_xParams
->getCount(); i
<nCount
; ++i
, ++pValues
)
263 Reference
< XPropertySet
> xParamAsSet
;
264 m_xParams
->getByIndex(i
) >>= xParamAsSet
;
267 pValues
->Value
>>= sValue
;
268 pValues
->Value
<<= OUString( m_aPredicateInput
.getPredicateValue( sValue
, xParamAsSet
, sal_False
) );
273 DBG_UNHANDLED_EXCEPTION();
277 // to close the dialog (which is more code than a simple EndDialog)
278 m_aOKBtn
.SetClickHdl(Link());
281 else if (&m_aTravelNext
== pButton
)
283 sal_uInt16 nCurrent
= m_aAllParams
.GetSelectEntryPos();
284 sal_uInt16 nCount
= m_aAllParams
.GetEntryCount();
285 OSL_ENSURE(nCount
== m_aVisitedParams
.size(), "OParameterDialog::OnButtonClicked : inconsistent lists !");
287 // search the next entry in list we haven't visited yet
288 sal_uInt16 nNext
= (nCurrent
+ 1) % nCount
;
289 while ((nNext
!= nCurrent
) && ( m_aVisitedParams
[nNext
] & EF_VISITED
))
290 nNext
= (nNext
+ 1) % nCount
;
292 if ( m_aVisitedParams
[nNext
] & EF_VISITED
)
293 // there is no such "not visited yet" entry -> simpy take the next one
294 nNext
= (nCurrent
+ 1) % nCount
;
296 m_aAllParams
.SelectEntryPos(nNext
);
297 LINK(this, OParameterDialog
, OnEntrySelected
).Call(&m_aAllParams
);
298 m_bNeedErrorOnCurrent
= sal_True
;
299 // we're are out of the complex web :) of direct and indirect calls to OnValueLoseFocus now,
300 // so the next time it is called we need an error message, again ....
301 // (TODO : there surely are better solutions for this ...)
307 //------------------------------------------------------------------------------
308 IMPL_LINK(OParameterDialog
, OnEntrySelected
, ListBox
*, /*pList*/)
310 if (m_aResetVisitFlag
.IsActive())
312 LINK(this, OParameterDialog
, OnVisitedTimeout
).Call(&m_aResetVisitFlag
);
313 m_aResetVisitFlag
.Stop();
315 // save the old values
316 if (m_nCurrentlySelected
!= LISTBOX_ENTRY_NOTFOUND
)
318 // do the transformation of the current text
319 if (LINK(this, OParameterDialog
, OnValueLoseFocus
).Call(&m_aParam
) != 0L)
320 { // there was an error interpreting the text
321 m_aAllParams
.SelectEntryPos(m_nCurrentlySelected
);
325 m_aFinalValues
[m_nCurrentlySelected
].Value
<<= OUString(m_aParam
.GetText());
328 // initialize the controls with the new values
329 sal_uInt16 nSelected
= m_aAllParams
.GetSelectEntryPos();
330 OSL_ENSURE(nSelected
!= LISTBOX_ENTRY_NOTFOUND
, "OParameterDialog::OnEntrySelected : no current entry !");
332 m_aParam
.SetText(::comphelper::getString(m_aFinalValues
[nSelected
].Value
));
333 m_nCurrentlySelected
= nSelected
;
335 // with this the value isn't dirty
336 OSL_ENSURE(m_nCurrentlySelected
< m_aVisitedParams
.size(), "OParameterDialog::OnEntrySelected : invalid current entry !");
337 m_aVisitedParams
[m_nCurrentlySelected
] &= ~EF_DIRTY
;
339 m_aResetVisitFlag
.SetTimeout(1000);
340 m_aResetVisitFlag
.Start();
345 //------------------------------------------------------------------------------
346 IMPL_LINK(OParameterDialog
, OnVisitedTimeout
, Timer
*, /*pTimer*/)
348 OSL_ENSURE(m_nCurrentlySelected
!= LISTBOX_ENTRY_NOTFOUND
, "OParameterDialog::OnVisitedTimeout : invalid call !");
350 // mark the currently selected entry as visited
351 OSL_ENSURE(m_nCurrentlySelected
< m_aVisitedParams
.size(), "OParameterDialog::OnVisitedTimeout : invalid entry !");
352 m_aVisitedParams
[m_nCurrentlySelected
] |= EF_VISITED
;
354 // was it the last "not visited yet" entry ?
355 ConstByteVectorIterator aIter
;
356 for ( aIter
= m_aVisitedParams
.begin();
357 aIter
< m_aVisitedParams
.end();
361 if (((*aIter
) & EF_VISITED
) == 0)
364 if (aIter
== m_aVisitedParams
.end())
365 { // yes, there isn't another one -> change the "default button"
366 m_aTravelNext
.SetStyle(m_aTravelNext
.GetStyle() & ~WB_DEFBUTTON
);
367 m_aOKBtn
.SetStyle(m_aOKBtn
.GetStyle() | WB_DEFBUTTON
);
369 // set to focus to one of the buttons temporary (with this their "default"-state is really updated)
370 Window
* pOldFocus
= Application::GetFocusWindow();
372 // if the old focus window is the value edit do some preparations ...
374 if (pOldFocus
== &m_aParam
)
376 m_aParam
.SetLoseFocusHdl(Link());
377 aSel
= m_aParam
.GetSelection();
379 m_aTravelNext
.GrabFocus();
381 pOldFocus
->GrabFocus();
383 // restore the settings for the value edit
384 if (pOldFocus
== &m_aParam
)
386 m_aParam
.SetLoseFocusHdl(LINK(this, OParameterDialog
, OnValueLoseFocus
));
387 m_aParam
.SetSelection(aSel
);
394 //------------------------------------------------------------------------------
395 IMPL_LINK(OParameterDialog
, OnValueModified
, Control
*, /*pBox*/)
397 // mark the currently selected entry as dirty
398 OSL_ENSURE(m_nCurrentlySelected
< m_aVisitedParams
.size(), "OParameterDialog::OnValueModified : invalid entry !");
399 m_aVisitedParams
[m_nCurrentlySelected
] |= EF_DIRTY
;
401 m_bNeedErrorOnCurrent
= sal_True
;
407 //.........................................................................
409 //.........................................................................
411 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */