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 .
20 #include "paramdialog.hxx"
21 #include "dbu_dlg.hrc"
22 #include "commontypes.hxx"
23 #include "moduledbu.hxx"
24 #include <com/sun/star/util/NumberFormatter.hpp>
25 #include <com/sun/star/sdbc/DataType.hpp>
26 #include <comphelper/processfactory.hxx>
27 #include <connectivity/dbtools.hxx>
28 #include "dbustrings.hrc"
29 #include <vcl/svapp.hxx>
30 #include <vcl/layout.hxx>
31 #include <osl/diagnose.h>
32 #include <tools/diagnose_ex.h>
33 #include "localresaccess.hxx"
34 #include <unotools/syslocale.hxx>
36 #define EF_VISITED 0x0001
37 #define EF_DIRTY 0x0002
42 using namespace ::com::sun::star::uno
;
43 using namespace ::com::sun::star::lang
;
44 using namespace ::com::sun::star::beans
;
45 using namespace ::com::sun::star::container
;
46 using namespace ::com::sun::star::sdbc
;
47 using namespace ::com::sun::star::util
;
48 using namespace ::connectivity
;
53 OParameterDialog::OParameterDialog(
54 vcl::Window
* pParent
, const Reference
< XIndexAccess
> & rParamContainer
,
55 const Reference
< XConnection
> & _rxConnection
, const Reference
< XComponentContext
>& rxContext
)
56 :ModalDialog( pParent
, "Parameters", "dbaccess/ui/parametersdialog.ui")
57 ,m_nCurrentlySelected(LISTBOX_ENTRY_NOTFOUND
)
58 ,m_xConnection(_rxConnection
)
59 ,m_aPredicateInput( rxContext
, _rxConnection
, getParseContext() )
60 ,m_bNeedErrorOnCurrent(true)
62 get(m_pAllParams
, "allParamTreeview");
63 get(m_pParam
, "paramEntry");
64 get(m_pTravelNext
, "next");
66 get(m_pCancelBtn
, "cancel");
68 set_height_request(200);
71 m_xFormatter
= Reference
< XNumberFormatter
>( NumberFormatter::create( rxContext
), UNO_QUERY_THROW
);
73 OSL_FAIL("OParameterDialog::OParameterDialog: need a service factory!");
76 Reference
< XNumberFormatsSupplier
> xNumberFormats
= ::dbtools::getNumberFormats(m_xConnection
, true);
77 if (!xNumberFormats
.is())
78 ::comphelper::disposeComponent(m_xFormatter
);
80 m_xFormatter
->attachNumberFormatsSupplier(xNumberFormats
);
83 OSL_ENSURE(rParamContainer
->getCount(), "OParameterDialog::OParameterDialog : can't handle empty containers !");
85 m_aFinalValues
.realloc(rParamContainer
->getCount());
86 PropertyValue
* pValues
= m_aFinalValues
.getArray();
88 for (sal_Int32 i
= 0, nCount
= rParamContainer
->getCount(); i
<nCount
; ++i
, ++pValues
)
90 Reference
< XPropertySet
> xParamAsSet
;
91 rParamContainer
->getByIndex(i
) >>= xParamAsSet
;
92 OSL_ENSURE(xParamAsSet
.is(),"Parameter is null!");
95 pValues
->Name
= ::comphelper::getString(xParamAsSet
->getPropertyValue(PROPERTY_NAME
));
96 m_pAllParams
->InsertEntry(pValues
->Name
);
98 m_aVisitedParams
.push_back(0);
99 // not visited, not dirty
102 m_xParams
= rParamContainer
;
106 DBG_UNHANDLED_EXCEPTION();
111 m_aResetVisitFlag
.SetTimeoutHdl(LINK(this, OParameterDialog
, OnVisitedTimeout
));
114 OParameterDialog::~OParameterDialog()
119 void OParameterDialog::dispose()
121 if (m_aResetVisitFlag
.IsActive())
122 m_aResetVisitFlag
.Stop();
123 m_pAllParams
.clear();
125 m_pTravelNext
.clear();
127 m_pCancelBtn
.clear();
128 ModalDialog::dispose();
131 void OParameterDialog::Construct()
133 m_pAllParams
->SetSelectHdl(LINK(this, OParameterDialog
, OnEntrySelected
));
134 m_pParam
->SetLoseFocusHdl(LINK(this, OParameterDialog
, OnValueLoseFocus
));
135 m_pParam
->SetModifyHdl(LINK(this, OParameterDialog
, OnValueModified
));
136 m_pTravelNext
->SetClickHdl(LINK(this, OParameterDialog
, OnButtonClicked
));
137 m_pOKBtn
->SetClickHdl(LINK(this, OParameterDialog
, OnButtonClicked
));
138 m_pCancelBtn
->SetClickHdl(LINK(this, OParameterDialog
, OnButtonClicked
));
140 if (m_pAllParams
->GetEntryCount())
142 m_pAllParams
->SelectEntryPos(0);
143 LINK(this, OParameterDialog
, OnEntrySelected
).Call(m_pAllParams
);
145 if (m_pAllParams
->GetEntryCount() == 1)
147 m_pTravelNext
->Enable(false);
150 if (m_pAllParams
->GetEntryCount() > 1)
152 m_pOKBtn
->SetStyle(m_pOKBtn
->GetStyle() & ~WB_DEFBUTTON
);
153 m_pTravelNext
->SetStyle(m_pTravelNext
->GetStyle() | WB_DEFBUTTON
);
157 m_pParam
->GrabFocus();
160 IMPL_LINK(OParameterDialog
, OnValueLoseFocus
, Control
*, /*pSource*/)
162 if (m_nCurrentlySelected
!= LISTBOX_ENTRY_NOTFOUND
)
164 if ( ( m_aVisitedParams
[ m_nCurrentlySelected
] & EF_DIRTY
) == 0 )
165 // nothing to do, the value isn't dirty
169 Reference
< XPropertySet
> xParamAsSet
;
170 m_xParams
->getByIndex(m_nCurrentlySelected
) >>= xParamAsSet
;
171 if (xParamAsSet
.is())
173 if (m_xConnection
.is() && m_xFormatter
.is())
175 OUString
sParamValue( m_pParam
->GetText() );
176 bool bValid
= m_aPredicateInput
.normalizePredicateString( sParamValue
, xParamAsSet
);
177 m_pParam
->SetText( sParamValue
);
180 // with this the value isn't dirty anymore
181 if (m_nCurrentlySelected
!= LISTBOX_ENTRY_NOTFOUND
)
182 m_aVisitedParams
[m_nCurrentlySelected
] &= ~EF_DIRTY
;
186 if (!m_bNeedErrorOnCurrent
)
192 sName
= ::comphelper::getString(xParamAsSet
->getPropertyValue(PROPERTY_NAME
));
196 DBG_UNHANDLED_EXCEPTION();
199 OUString
sMessage(ModuleRes(STR_COULD_NOT_CONVERT_PARAM
));
200 sMessage
= sMessage
.replaceAll( "$name$", sName
);
201 ScopedVclPtrInstance
<MessageDialog
>::Create(nullptr, sMessage
)->Execute();
202 m_pParam
->GrabFocus();
211 IMPL_LINK(OParameterDialog
, OnButtonClicked
, PushButton
*, pButton
)
213 if (m_pCancelBtn
== pButton
)
215 // no interpreting of the given values anymore ....
216 m_pParam
->SetLoseFocusHdl(Link
<>()); // no direct call from the control anymore ...
217 m_bNeedErrorOnCurrent
= false; // in case of any indirect calls -> no error message
218 m_pCancelBtn
->SetClickHdl(Link
<>());
219 m_pCancelBtn
->Click();
221 else if (m_pOKBtn
== pButton
)
223 // transfer the current values into the Any
224 if (LINK(this, OParameterDialog
, OnEntrySelected
).Call(m_pAllParams
) != 0L)
225 { // there was an error interpreting the current text
226 m_bNeedErrorOnCurrent
= true;
227 // we're are out of the complex web :) of direct and indirect calls to OnValueLoseFocus now,
228 // so the next time it is called we need an error message, again ....
229 // (TODO : there surely are better solutions for this ...)
235 // write the parameters
238 PropertyValue
* pValues
= m_aFinalValues
.getArray();
239 for (sal_Int32 i
= 0, nCount
= m_xParams
->getCount(); i
<nCount
; ++i
, ++pValues
)
241 Reference
< XPropertySet
> xParamAsSet
;
242 m_xParams
->getByIndex(i
) >>= xParamAsSet
;
245 pValues
->Value
>>= sValue
;
246 pValues
->Value
<<= m_aPredicateInput
.getPredicateValue( sValue
, xParamAsSet
);
251 DBG_UNHANDLED_EXCEPTION();
255 // to close the dialog (which is more code than a simple EndDialog)
256 m_pOKBtn
->SetClickHdl(Link
<>());
259 else if (m_pTravelNext
== pButton
)
261 sal_Int32 nCurrent
= m_pAllParams
->GetSelectEntryPos();
262 sal_Int32 nCount
= m_pAllParams
->GetEntryCount();
263 OSL_ENSURE(static_cast<size_t>(nCount
) == m_aVisitedParams
.size(), "OParameterDialog::OnButtonClicked : inconsistent lists !");
265 // search the next entry in list we haven't visited yet
266 sal_Int32 nNext
= (nCurrent
+ 1) % nCount
;
267 while ((nNext
!= nCurrent
) && ( m_aVisitedParams
[nNext
] & EF_VISITED
))
268 nNext
= (nNext
+ 1) % nCount
;
270 if ( m_aVisitedParams
[nNext
] & EF_VISITED
)
271 // there is no such "not visited yet" entry -> simpy take the next one
272 nNext
= (nCurrent
+ 1) % nCount
;
274 m_pAllParams
->SelectEntryPos(nNext
);
275 LINK(this, OParameterDialog
, OnEntrySelected
).Call(m_pAllParams
);
276 m_bNeedErrorOnCurrent
= true;
277 // we're are out of the complex web :) of direct and indirect calls to OnValueLoseFocus now,
278 // so the next time it is called we need an error message, again ....
279 // (TODO : there surely are better solutions for this ...)
285 IMPL_LINK(OParameterDialog
, OnEntrySelected
, ListBox
*, /*pList*/)
287 if (m_aResetVisitFlag
.IsActive())
289 LINK(this, OParameterDialog
, OnVisitedTimeout
).Call(&m_aResetVisitFlag
);
290 m_aResetVisitFlag
.Stop();
292 // save the old values
293 if (m_nCurrentlySelected
!= LISTBOX_ENTRY_NOTFOUND
)
295 // do the transformation of the current text
296 if (LINK(this, OParameterDialog
, OnValueLoseFocus
).Call(m_pParam
) != 0L)
297 { // there was an error interpreting the text
298 m_pAllParams
->SelectEntryPos(m_nCurrentlySelected
);
302 m_aFinalValues
[m_nCurrentlySelected
].Value
<<= OUString(m_pParam
->GetText());
305 // initialize the controls with the new values
306 sal_Int32 nSelected
= m_pAllParams
->GetSelectEntryPos();
307 OSL_ENSURE(nSelected
!= LISTBOX_ENTRY_NOTFOUND
, "OParameterDialog::OnEntrySelected : no current entry !");
309 m_pParam
->SetText(::comphelper::getString(m_aFinalValues
[nSelected
].Value
));
310 m_nCurrentlySelected
= nSelected
;
312 // with this the value isn't dirty
313 OSL_ENSURE(static_cast<size_t>(m_nCurrentlySelected
) < m_aVisitedParams
.size(), "OParameterDialog::OnEntrySelected : invalid current entry !");
314 m_aVisitedParams
[m_nCurrentlySelected
] &= ~EF_DIRTY
;
316 m_aResetVisitFlag
.SetTimeout(1000);
317 m_aResetVisitFlag
.Start();
322 IMPL_LINK_NOARG_TYPED(OParameterDialog
, OnVisitedTimeout
, Timer
*, void)
324 OSL_ENSURE(m_nCurrentlySelected
!= LISTBOX_ENTRY_NOTFOUND
, "OParameterDialog::OnVisitedTimeout : invalid call !");
326 // mark the currently selected entry as visited
327 OSL_ENSURE(static_cast<size_t>(m_nCurrentlySelected
) < m_aVisitedParams
.size(), "OParameterDialog::OnVisitedTimeout : invalid entry !");
328 m_aVisitedParams
[m_nCurrentlySelected
] |= EF_VISITED
;
330 // was it the last "not visited yet" entry ?
331 ByteVector::const_iterator aIter
;
332 for ( aIter
= m_aVisitedParams
.begin();
333 aIter
< m_aVisitedParams
.end();
337 if (((*aIter
) & EF_VISITED
) == 0)
340 if (aIter
== m_aVisitedParams
.end())
341 { // yes, there isn't another one -> change the "default button"
342 m_pTravelNext
->SetStyle(m_pTravelNext
->GetStyle() & ~WB_DEFBUTTON
);
343 m_pOKBtn
->SetStyle(m_pOKBtn
->GetStyle() | WB_DEFBUTTON
);
345 // set to focus to one of the buttons temporary (with this their "default"-state is really updated)
346 vcl::Window
* pOldFocus
= Application::GetFocusWindow();
348 // if the old focus window is the value edit do some preparations ...
350 if (pOldFocus
== m_pParam
)
352 m_pParam
->SetLoseFocusHdl(Link
<>());
353 aSel
= m_pParam
->GetSelection();
355 m_pTravelNext
->GrabFocus();
357 pOldFocus
->GrabFocus();
359 // restore the settings for the value edit
360 if (pOldFocus
== m_pParam
)
362 m_pParam
->SetLoseFocusHdl(LINK(this, OParameterDialog
, OnValueLoseFocus
));
363 m_pParam
->SetSelection(aSel
);
368 IMPL_LINK(OParameterDialog
, OnValueModified
, Control
*, /*pBox*/)
370 // mark the currently selected entry as dirty
371 OSL_ENSURE(static_cast<size_t>(m_nCurrentlySelected
) < m_aVisitedParams
.size(), "OParameterDialog::OnValueModified : invalid entry !");
372 m_aVisitedParams
[m_nCurrentlySelected
] |= EF_DIRTY
;
374 m_bNeedErrorOnCurrent
= true;
381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */