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 <core_resource.hxx>
21 #include <paramdialog.hxx>
22 #include <strings.hrc>
23 #include <strings.hxx>
24 #include <com/sun/star/util/NumberFormatter.hpp>
25 #include <comphelper/types.hxx>
26 #include <connectivity/dbtools.hxx>
27 #include <vcl/weld.hxx>
28 #include <o3tl/safeint.hxx>
29 #include <osl/diagnose.h>
30 #include <comphelper/diagnose_ex.hxx>
35 using namespace ::com::sun::star::uno
;
36 using namespace ::com::sun::star::lang
;
37 using namespace ::com::sun::star::beans
;
38 using namespace ::com::sun::star::container
;
39 using namespace ::com::sun::star::sdbc
;
40 using namespace ::com::sun::star::util
;
41 using namespace ::connectivity
;
46 OParameterDialog::OParameterDialog(
47 weld::Window
* pParent
, const Reference
< XIndexAccess
> & rParamContainer
,
48 const Reference
< XConnection
> & _rxConnection
, const Reference
< XComponentContext
>& rxContext
)
49 : GenericDialogController(pParent
, "dbaccess/ui/parametersdialog.ui", "Parameters")
50 , m_nCurrentlySelected(-1)
51 , m_xConnection(_rxConnection
)
52 , m_aPredicateInput( rxContext
, _rxConnection
, getParseContext() )
53 , m_aResetVisitFlag("dbaccess OParameterDialog m_aResetVisitFlag")
54 , m_xAllParams(m_xBuilder
->weld_tree_view("allParamTreeview"))
55 , m_xParam(m_xBuilder
->weld_entry("paramEntry"))
56 , m_xTravelNext(m_xBuilder
->weld_button("next"))
57 , m_xOKBtn(m_xBuilder
->weld_button("ok"))
58 , m_xCancelBtn(m_xBuilder
->weld_button("cancel"))
60 m_xAllParams
->set_size_request(-1, m_xAllParams
->get_height_rows(10));
63 m_xFormatter
.set( NumberFormatter::create( rxContext
), UNO_QUERY_THROW
);
65 OSL_FAIL("OParameterDialog::OParameterDialog: need a service factory!");
68 Reference
< XNumberFormatsSupplier
> xNumberFormats
= ::dbtools::getNumberFormats(m_xConnection
, true);
69 if (!xNumberFormats
.is())
70 ::comphelper::disposeComponent(m_xFormatter
);
72 m_xFormatter
->attachNumberFormatsSupplier(xNumberFormats
);
75 OSL_ENSURE(rParamContainer
->getCount(), "OParameterDialog::OParameterDialog : can't handle empty containers !");
77 m_aFinalValues
.realloc(rParamContainer
->getCount());
78 PropertyValue
* pValues
= m_aFinalValues
.getArray();
80 for (sal_Int32 i
= 0, nCount
= rParamContainer
->getCount(); i
<nCount
; ++i
, ++pValues
)
82 Reference
< XPropertySet
> xParamAsSet
;
83 rParamContainer
->getByIndex(i
) >>= xParamAsSet
;
84 OSL_ENSURE(xParamAsSet
.is(),"Parameter is null!");
87 pValues
->Name
= ::comphelper::getString(xParamAsSet
->getPropertyValue(PROPERTY_NAME
));
88 m_xAllParams
->append_text(pValues
->Name
);
90 m_aVisitedParams
.push_back(VisitFlags::NONE
);
91 // not visited, not dirty
94 m_xParams
= rParamContainer
;
98 DBG_UNHANDLED_EXCEPTION("dbaccess");
103 m_aResetVisitFlag
.SetInvokeHandler(LINK(this, OParameterDialog
, OnVisitedTimeout
));
106 OParameterDialog::~OParameterDialog()
108 if (m_aResetVisitFlag
.IsActive())
109 m_aResetVisitFlag
.Stop();
112 void OParameterDialog::Construct()
114 m_xAllParams
->connect_changed(LINK(this, OParameterDialog
, OnEntryListBoxSelected
));
115 m_xParam
->connect_focus_out(LINK(this, OParameterDialog
, OnValueLoseFocusHdl
));
116 m_xParam
->connect_changed(LINK(this, OParameterDialog
, OnValueModified
));
117 m_xTravelNext
->connect_clicked(LINK(this, OParameterDialog
, OnButtonClicked
));
118 m_xOKBtn
->connect_clicked(LINK(this, OParameterDialog
, OnButtonClicked
));
119 m_xCancelBtn
->connect_clicked(LINK(this, OParameterDialog
, OnButtonClicked
));
121 if (m_xAllParams
->n_children())
123 m_xAllParams
->select(0);
126 if (m_xAllParams
->n_children() == 1)
127 m_xTravelNext
->set_sensitive(false);
129 if (m_xAllParams
->n_children() > 1)
130 m_xDialog
->change_default_widget(m_xOKBtn
.get(), m_xTravelNext
.get());
133 m_xParam
->grab_focus();
136 IMPL_LINK_NOARG(OParameterDialog
, OnValueLoseFocusHdl
, weld::Widget
&, void)
138 CheckValueForError();
141 bool OParameterDialog::CheckValueForError()
143 if (m_nCurrentlySelected
!= -1)
145 if ( !( m_aVisitedParams
[ m_nCurrentlySelected
] & VisitFlags::Dirty
) )
146 // nothing to do, the value isn't dirty
152 Reference
< XPropertySet
> xParamAsSet
;
153 m_xParams
->getByIndex(m_nCurrentlySelected
) >>= xParamAsSet
;
154 if (xParamAsSet
.is())
156 if (m_xConnection
.is() && m_xFormatter
.is())
158 OUString
sParamValue(m_xParam
->get_text());
159 bool bValid
= m_aPredicateInput
.normalizePredicateString( sParamValue
, xParamAsSet
);
160 m_xParam
->set_text(sParamValue
);
161 m_xParam
->set_message_type(bValid
? weld::EntryMessageType::Normal
: weld::EntryMessageType::Error
);
165 // with this the value isn't dirty anymore
166 if (m_nCurrentlySelected
!= -1)
167 m_aVisitedParams
[m_nCurrentlySelected
] &= ~VisitFlags::Dirty
;
174 sName
= ::comphelper::getString(xParamAsSet
->getPropertyValue(PROPERTY_NAME
));
178 DBG_UNHANDLED_EXCEPTION("dbaccess");
181 OUString
sMessage(DBA_RES(STR_COULD_NOT_CONVERT_PARAM
));
182 sToolTip
= sMessage
.replaceAll( "$name$", sName
);
183 m_xParam
->grab_focus();
186 m_xParam
->set_tooltip_text(sToolTip
);
187 m_xOKBtn
->set_sensitive(bValid
);
194 IMPL_LINK(OParameterDialog
, OnButtonClicked
, weld::Button
&, rButton
, void)
196 if (m_xCancelBtn
.get() == &rButton
)
198 // no interpreting of the given values anymore...
199 m_xParam
->connect_focus_out(Link
<weld::Widget
&, void>()); // no direct call from the control anymore ...
200 m_xDialog
->response(RET_CANCEL
);
202 else if (m_xOKBtn
.get() == &rButton
)
204 // transfer the current values into the Any
205 if (OnEntrySelected())
206 { // there was an error interpreting the current text
212 // write the parameters
215 PropertyValue
* pValues
= m_aFinalValues
.getArray();
216 for (sal_Int32 i
= 0, nCount
= m_xParams
->getCount(); i
<nCount
; ++i
, ++pValues
)
218 Reference
< XPropertySet
> xParamAsSet
;
219 m_xParams
->getByIndex(i
) >>= xParamAsSet
;
222 pValues
->Value
>>= sValue
;
223 pValues
->Value
= m_aPredicateInput
.getPredicateValue( sValue
, xParamAsSet
);
228 DBG_UNHANDLED_EXCEPTION("dbaccess");
232 m_xDialog
->response(RET_OK
);
234 else if (m_xTravelNext
.get() == &rButton
)
236 if (sal_Int32 nCount
= m_xAllParams
->n_children())
238 sal_Int32 nCurrent
= m_xAllParams
->get_selected_index();
239 OSL_ENSURE(static_cast<size_t>(nCount
) == m_aVisitedParams
.size(), "OParameterDialog::OnButtonClicked : inconsistent lists !");
241 // search the next entry in list we haven't visited yet
242 sal_Int32 nNext
= (nCurrent
+ 1) % nCount
;
243 while ((nNext
!= nCurrent
) && ( m_aVisitedParams
[nNext
] & VisitFlags::Visited
))
244 nNext
= (nNext
+ 1) % nCount
;
246 if ( m_aVisitedParams
[nNext
] & VisitFlags::Visited
)
247 // there is no such "not visited yet" entry -> simply take the next one
248 nNext
= (nCurrent
+ 1) % nCount
;
250 m_xAllParams
->select(nNext
);
256 IMPL_LINK_NOARG(OParameterDialog
, OnEntryListBoxSelected
, weld::TreeView
&, void)
261 bool OParameterDialog::OnEntrySelected()
263 if (m_aResetVisitFlag
.IsActive())
265 LINK(this, OParameterDialog
, OnVisitedTimeout
).Call(&m_aResetVisitFlag
);
266 m_aResetVisitFlag
.Stop();
268 // save the old values
269 if (m_nCurrentlySelected
!= -1)
271 // do the transformation of the current text
272 if (CheckValueForError())
273 { // there was an error interpreting the text
274 m_xAllParams
->select(m_nCurrentlySelected
);
278 m_aFinalValues
.getArray()[m_nCurrentlySelected
].Value
<<= m_xParam
->get_text();
281 // initialize the controls with the new values
282 sal_Int32 nSelected
= m_xAllParams
->get_selected_index();
283 OSL_ENSURE(nSelected
!= -1, "OParameterDialog::OnEntrySelected : no current entry !");
285 m_xParam
->set_text(::comphelper::getString(m_aFinalValues
[nSelected
].Value
));
286 m_nCurrentlySelected
= nSelected
;
288 // with this the value isn't dirty
289 OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected
) < m_aVisitedParams
.size(), "OParameterDialog::OnEntrySelected : invalid current entry !");
290 m_aVisitedParams
[m_nCurrentlySelected
] &= ~VisitFlags::Dirty
;
292 m_aResetVisitFlag
.SetTimeout(1000);
293 m_aResetVisitFlag
.Start();
298 IMPL_LINK_NOARG(OParameterDialog
, OnVisitedTimeout
, Timer
*, void)
300 OSL_ENSURE(m_nCurrentlySelected
!= -1, "OParameterDialog::OnVisitedTimeout : invalid call !");
302 // mark the currently selected entry as visited
303 OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected
) < m_aVisitedParams
.size(), "OParameterDialog::OnVisitedTimeout : invalid entry !");
304 m_aVisitedParams
[m_nCurrentlySelected
] |= VisitFlags::Visited
;
306 // was it the last "not visited yet" entry ?
307 bool bVisited
= false;
308 for (auto const& visitedParam
: m_aVisitedParams
)
310 if (!(visitedParam
& VisitFlags::Visited
))
319 // yes, there isn't another one -> change the "default button"
320 m_xDialog
->change_default_widget(m_xTravelNext
.get(), m_xOKBtn
.get());
324 IMPL_LINK(OParameterDialog
, OnValueModified
, weld::Entry
&, rEdit
, void)
326 // mark the currently selected entry as dirty
327 OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected
) < m_aVisitedParams
.size(), "OParameterDialog::OnValueModified : invalid entry !");
328 m_aVisitedParams
[m_nCurrentlySelected
] |= VisitFlags::Dirty
;
329 rEdit
.set_message_type(weld::EntryMessageType::Normal
);
334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */