Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
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>
35 :
36 : #define EF_VISITED 0x0001
37 : #define EF_DIRTY 0x0002
38 :
39 : namespace dbaui
40 : {
41 :
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;
49 :
50 : // OParameterDialog
51 :
52 :
53 0 : 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 0 : ,m_aPredicateInput( rxContext, _rxConnection, getParseContext() )
60 0 : ,m_bNeedErrorOnCurrent(true)
61 : {
62 0 : get(m_pAllParams, "allParamTreeview");
63 0 : get(m_pParam, "paramEntry");
64 0 : get(m_pTravelNext, "next");
65 0 : get(m_pOKBtn, "ok");
66 0 : get(m_pCancelBtn, "cancel");
67 :
68 0 : set_height_request(200);
69 :
70 0 : if (rxContext.is())
71 0 : m_xFormatter = Reference< XNumberFormatter>( NumberFormatter::create( rxContext ), UNO_QUERY_THROW);
72 : else {
73 : OSL_FAIL("OParameterDialog::OParameterDialog: need a service factory!");
74 : }
75 :
76 0 : Reference< XNumberFormatsSupplier > xNumberFormats = ::dbtools::getNumberFormats(m_xConnection, true);
77 0 : if (!xNumberFormats.is())
78 0 : ::comphelper::disposeComponent(m_xFormatter);
79 : else
80 0 : m_xFormatter->attachNumberFormatsSupplier(xNumberFormats);
81 : try
82 : {
83 : OSL_ENSURE(rParamContainer->getCount(), "OParameterDialog::OParameterDialog : can't handle empty containers !");
84 :
85 0 : m_aFinalValues.realloc(rParamContainer->getCount());
86 0 : PropertyValue* pValues = m_aFinalValues.getArray();
87 :
88 0 : for (sal_Int32 i = 0, nCount = rParamContainer->getCount(); i<nCount; ++i, ++pValues)
89 : {
90 0 : Reference< XPropertySet > xParamAsSet;
91 0 : rParamContainer->getByIndex(i) >>= xParamAsSet;
92 : OSL_ENSURE(xParamAsSet.is(),"Parameter is null!");
93 0 : if(!xParamAsSet.is())
94 0 : continue;
95 0 : pValues->Name = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME));
96 0 : m_pAllParams->InsertEntry(pValues->Name);
97 :
98 0 : m_aVisitedParams.push_back(0);
99 : // not visited, not dirty
100 0 : }
101 :
102 0 : m_xParams = rParamContainer;
103 : }
104 0 : catch(Exception&)
105 : {
106 : DBG_UNHANDLED_EXCEPTION();
107 : }
108 :
109 0 : Construct();
110 :
111 0 : m_aResetVisitFlag.SetTimeoutHdl(LINK(this, OParameterDialog, OnVisitedTimeout));
112 0 : }
113 :
114 0 : OParameterDialog::~OParameterDialog()
115 : {
116 0 : disposeOnce();
117 0 : }
118 :
119 0 : void OParameterDialog::dispose()
120 : {
121 0 : if (m_aResetVisitFlag.IsActive())
122 0 : m_aResetVisitFlag.Stop();
123 0 : m_pAllParams.clear();
124 0 : m_pParam.clear();
125 0 : m_pTravelNext.clear();
126 0 : m_pOKBtn.clear();
127 0 : m_pCancelBtn.clear();
128 0 : ModalDialog::dispose();
129 0 : }
130 :
131 0 : void OParameterDialog::Construct()
132 : {
133 0 : m_pAllParams->SetSelectHdl(LINK(this, OParameterDialog, OnEntrySelected));
134 0 : m_pParam->SetLoseFocusHdl(LINK(this, OParameterDialog, OnValueLoseFocus));
135 0 : m_pParam->SetModifyHdl(LINK(this, OParameterDialog, OnValueModified));
136 0 : m_pTravelNext->SetClickHdl(LINK(this, OParameterDialog, OnButtonClicked));
137 0 : m_pOKBtn->SetClickHdl(LINK(this, OParameterDialog, OnButtonClicked));
138 0 : m_pCancelBtn->SetClickHdl(LINK(this, OParameterDialog, OnButtonClicked));
139 :
140 0 : if (m_pAllParams->GetEntryCount())
141 : {
142 0 : m_pAllParams->SelectEntryPos(0);
143 0 : LINK(this, OParameterDialog, OnEntrySelected).Call(m_pAllParams);
144 :
145 0 : if (m_pAllParams->GetEntryCount() == 1)
146 : {
147 0 : m_pTravelNext->Enable(false);
148 : }
149 :
150 0 : if (m_pAllParams->GetEntryCount() > 1)
151 : {
152 0 : m_pOKBtn->SetStyle(m_pOKBtn->GetStyle() & ~WB_DEFBUTTON);
153 0 : m_pTravelNext->SetStyle(m_pTravelNext->GetStyle() | WB_DEFBUTTON);
154 : }
155 : }
156 :
157 0 : m_pParam->GrabFocus();
158 0 : }
159 :
160 0 : IMPL_LINK(OParameterDialog, OnValueLoseFocus, Control*, /*pSource*/)
161 : {
162 0 : if (m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND)
163 : {
164 0 : if ( ( m_aVisitedParams[ m_nCurrentlySelected ] & EF_DIRTY ) == 0 )
165 : // nothing to do, the value isn't dirty
166 0 : return 0L;
167 : }
168 :
169 0 : Reference< XPropertySet > xParamAsSet;
170 0 : m_xParams->getByIndex(m_nCurrentlySelected) >>= xParamAsSet;
171 0 : if (xParamAsSet.is())
172 : {
173 0 : if (m_xConnection.is() && m_xFormatter.is())
174 : {
175 0 : OUString sParamValue( m_pParam->GetText() );
176 0 : bool bValid = m_aPredicateInput.normalizePredicateString( sParamValue, xParamAsSet );
177 0 : m_pParam->SetText( sParamValue );
178 0 : if ( bValid )
179 : {
180 : // with this the value isn't dirty anymore
181 0 : if (m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND)
182 0 : m_aVisitedParams[m_nCurrentlySelected] &= ~EF_DIRTY;
183 : }
184 : else
185 : {
186 0 : if (!m_bNeedErrorOnCurrent)
187 0 : return 1L;
188 :
189 0 : OUString sName;
190 : try
191 : {
192 0 : sName = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME));
193 : }
194 0 : catch(Exception&)
195 : {
196 : DBG_UNHANDLED_EXCEPTION();
197 : }
198 :
199 0 : OUString sMessage(ModuleRes(STR_COULD_NOT_CONVERT_PARAM));
200 0 : sMessage = sMessage.replaceAll( "$name$", sName );
201 0 : ScopedVclPtrInstance<MessageDialog>::Create(nullptr, sMessage)->Execute();
202 0 : m_pParam->GrabFocus();
203 0 : return 1L;
204 0 : }
205 : }
206 : }
207 :
208 0 : return 0L;
209 : }
210 :
211 0 : IMPL_LINK(OParameterDialog, OnButtonClicked, PushButton*, pButton)
212 : {
213 0 : if (m_pCancelBtn == pButton)
214 : {
215 : // no interpreting of the given values anymore ....
216 0 : m_pParam->SetLoseFocusHdl(Link<>()); // no direct call from the control anymore ...
217 0 : m_bNeedErrorOnCurrent = false; // in case of any indirect calls -> no error message
218 0 : m_pCancelBtn->SetClickHdl(Link<>());
219 0 : m_pCancelBtn->Click();
220 : }
221 0 : else if (m_pOKBtn == pButton)
222 : {
223 : // transfer the current values into the Any
224 0 : if (LINK(this, OParameterDialog, OnEntrySelected).Call(m_pAllParams) != 0L)
225 : { // there was an error interpreting the current text
226 0 : 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 ...)
230 0 : return 1L;
231 : }
232 :
233 0 : if (m_xParams.is())
234 : {
235 : // write the parameters
236 : try
237 : {
238 0 : PropertyValue* pValues = m_aFinalValues.getArray();
239 0 : for (sal_Int32 i = 0, nCount = m_xParams->getCount(); i<nCount; ++i, ++pValues)
240 : {
241 0 : Reference< XPropertySet > xParamAsSet;
242 0 : m_xParams->getByIndex(i) >>= xParamAsSet;
243 :
244 0 : OUString sValue;
245 0 : pValues->Value >>= sValue;
246 0 : pValues->Value <<= m_aPredicateInput.getPredicateValue( sValue, xParamAsSet );
247 0 : }
248 : }
249 0 : catch(Exception&)
250 : {
251 : DBG_UNHANDLED_EXCEPTION();
252 : }
253 :
254 : }
255 : // to close the dialog (which is more code than a simple EndDialog)
256 0 : m_pOKBtn->SetClickHdl(Link<>());
257 0 : m_pOKBtn->Click();
258 : }
259 0 : else if (m_pTravelNext == pButton)
260 : {
261 0 : sal_Int32 nCurrent = m_pAllParams->GetSelectEntryPos();
262 0 : sal_Int32 nCount = m_pAllParams->GetEntryCount();
263 : OSL_ENSURE(static_cast<size_t>(nCount) == m_aVisitedParams.size(), "OParameterDialog::OnButtonClicked : inconsistent lists !");
264 :
265 : // search the next entry in list we haven't visited yet
266 0 : sal_Int32 nNext = (nCurrent + 1) % nCount;
267 0 : while ((nNext != nCurrent) && ( m_aVisitedParams[nNext] & EF_VISITED ))
268 0 : nNext = (nNext + 1) % nCount;
269 :
270 0 : if ( m_aVisitedParams[nNext] & EF_VISITED )
271 : // there is no such "not visited yet" entry -> simpy take the next one
272 0 : nNext = (nCurrent + 1) % nCount;
273 :
274 0 : m_pAllParams->SelectEntryPos(nNext);
275 0 : LINK(this, OParameterDialog, OnEntrySelected).Call(m_pAllParams);
276 0 : 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 ...)
280 : }
281 :
282 0 : return 0L;
283 : }
284 :
285 0 : IMPL_LINK(OParameterDialog, OnEntrySelected, ListBox*, /*pList*/)
286 : {
287 0 : if (m_aResetVisitFlag.IsActive())
288 : {
289 0 : LINK(this, OParameterDialog, OnVisitedTimeout).Call(&m_aResetVisitFlag);
290 0 : m_aResetVisitFlag.Stop();
291 : }
292 : // save the old values
293 0 : if (m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND)
294 : {
295 : // do the transformation of the current text
296 0 : if (LINK(this, OParameterDialog, OnValueLoseFocus).Call(m_pParam) != 0L)
297 : { // there was an error interpreting the text
298 0 : m_pAllParams->SelectEntryPos(m_nCurrentlySelected);
299 0 : return 1L;
300 : }
301 :
302 0 : m_aFinalValues[m_nCurrentlySelected].Value <<= OUString(m_pParam->GetText());
303 : }
304 :
305 : // initialize the controls with the new values
306 0 : sal_Int32 nSelected = m_pAllParams->GetSelectEntryPos();
307 : OSL_ENSURE(nSelected != LISTBOX_ENTRY_NOTFOUND, "OParameterDialog::OnEntrySelected : no current entry !");
308 :
309 0 : m_pParam->SetText(::comphelper::getString(m_aFinalValues[nSelected].Value));
310 0 : m_nCurrentlySelected = nSelected;
311 :
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 0 : m_aVisitedParams[m_nCurrentlySelected] &= ~EF_DIRTY;
315 :
316 0 : m_aResetVisitFlag.SetTimeout(1000);
317 0 : m_aResetVisitFlag.Start();
318 :
319 0 : return 0L;
320 : }
321 :
322 0 : IMPL_LINK_NOARG_TYPED(OParameterDialog, OnVisitedTimeout, Timer*, void)
323 : {
324 : OSL_ENSURE(m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND, "OParameterDialog::OnVisitedTimeout : invalid call !");
325 :
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 0 : m_aVisitedParams[m_nCurrentlySelected] |= EF_VISITED;
329 :
330 : // was it the last "not visited yet" entry ?
331 0 : ByteVector::const_iterator aIter;
332 0 : for ( aIter = m_aVisitedParams.begin();
333 0 : aIter < m_aVisitedParams.end();
334 : ++aIter
335 : )
336 : {
337 0 : if (((*aIter) & EF_VISITED) == 0)
338 0 : break;
339 : }
340 0 : if (aIter == m_aVisitedParams.end())
341 : { // yes, there isn't another one -> change the "default button"
342 0 : m_pTravelNext->SetStyle(m_pTravelNext->GetStyle() & ~WB_DEFBUTTON);
343 0 : m_pOKBtn->SetStyle(m_pOKBtn->GetStyle() | WB_DEFBUTTON);
344 :
345 : // set to focus to one of the buttons temporary (with this their "default"-state is really updated)
346 0 : vcl::Window* pOldFocus = Application::GetFocusWindow();
347 :
348 : // if the old focus window is the value edit do some preparations ...
349 0 : Selection aSel;
350 0 : if (pOldFocus == m_pParam)
351 : {
352 0 : m_pParam->SetLoseFocusHdl(Link<>());
353 0 : aSel = m_pParam->GetSelection();
354 : }
355 0 : m_pTravelNext->GrabFocus();
356 0 : if (pOldFocus)
357 0 : pOldFocus->GrabFocus();
358 :
359 : // restore the settings for the value edit
360 0 : if (pOldFocus == m_pParam)
361 : {
362 0 : m_pParam->SetLoseFocusHdl(LINK(this, OParameterDialog, OnValueLoseFocus));
363 0 : m_pParam->SetSelection(aSel);
364 : }
365 : }
366 0 : }
367 :
368 0 : IMPL_LINK(OParameterDialog, OnValueModified, Control*, /*pBox*/)
369 : {
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 0 : m_aVisitedParams[m_nCurrentlySelected] |= EF_DIRTY;
373 :
374 0 : m_bNeedErrorOnCurrent = true;
375 :
376 0 : return 0L;
377 : }
378 :
379 36 : } // namespace dbaui
380 :
381 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|