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 : if (!pValues->Value.hasValue())
99 : // it won't have a value, 'cause it's default constructed. But may be later we support
100 : // initializing this dialog with values
101 0 : pValues->Value = makeAny( OUString() );
102 : // default the values to an empty string
103 :
104 0 : m_aVisitedParams.push_back(0);
105 : // not visited, not dirty
106 0 : }
107 :
108 0 : m_xParams = rParamContainer;
109 : }
110 0 : catch(Exception&)
111 : {
112 : DBG_UNHANDLED_EXCEPTION();
113 : }
114 :
115 0 : Construct();
116 :
117 0 : m_aResetVisitFlag.SetTimeoutHdl(LINK(this, OParameterDialog, OnVisitedTimeout));
118 0 : }
119 :
120 0 : OParameterDialog::~OParameterDialog()
121 : {
122 0 : if (m_aResetVisitFlag.IsActive())
123 0 : m_aResetVisitFlag.Stop();
124 :
125 0 : }
126 :
127 0 : void OParameterDialog::Construct()
128 : {
129 0 : m_pAllParams->SetSelectHdl(LINK(this, OParameterDialog, OnEntrySelected));
130 0 : m_pParam->SetLoseFocusHdl(LINK(this, OParameterDialog, OnValueLoseFocus));
131 0 : m_pParam->SetModifyHdl(LINK(this, OParameterDialog, OnValueModified));
132 0 : m_pTravelNext->SetClickHdl(LINK(this, OParameterDialog, OnButtonClicked));
133 0 : m_pOKBtn->SetClickHdl(LINK(this, OParameterDialog, OnButtonClicked));
134 0 : m_pCancelBtn->SetClickHdl(LINK(this, OParameterDialog, OnButtonClicked));
135 :
136 0 : if (m_pAllParams->GetEntryCount())
137 : {
138 0 : m_pAllParams->SelectEntryPos(0);
139 0 : LINK(this, OParameterDialog, OnEntrySelected).Call(m_pAllParams);
140 :
141 0 : if (m_pAllParams->GetEntryCount() == 1)
142 : {
143 0 : m_pTravelNext->Enable(false);
144 : }
145 :
146 0 : if (m_pAllParams->GetEntryCount() > 1)
147 : {
148 0 : m_pOKBtn->SetStyle(m_pOKBtn->GetStyle() & ~WB_DEFBUTTON);
149 0 : m_pTravelNext->SetStyle(m_pTravelNext->GetStyle() | WB_DEFBUTTON);
150 : }
151 : }
152 :
153 0 : m_pParam->GrabFocus();
154 0 : }
155 :
156 0 : IMPL_LINK(OParameterDialog, OnValueLoseFocus, Control*, /*pSource*/)
157 : {
158 0 : if (m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND)
159 : {
160 0 : if ( ( m_aVisitedParams[ m_nCurrentlySelected ] & EF_DIRTY ) == 0 )
161 : // nothing to do, the value isn't dirty
162 0 : return 0L;
163 : }
164 :
165 0 : Reference< XPropertySet > xParamAsSet;
166 0 : m_xParams->getByIndex(m_nCurrentlySelected) >>= xParamAsSet;
167 0 : if (xParamAsSet.is())
168 : {
169 0 : if (m_xConnection.is() && m_xFormatter.is())
170 : {
171 0 : OUString sParamValue( m_pParam->GetText() );
172 0 : bool bValid = m_aPredicateInput.normalizePredicateString( sParamValue, xParamAsSet );
173 0 : m_pParam->SetText( sParamValue );
174 0 : if ( bValid )
175 : {
176 : // with this the value isn't dirty anymore
177 0 : if (m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND)
178 0 : m_aVisitedParams[m_nCurrentlySelected] &= ~EF_DIRTY;
179 : }
180 : else
181 : {
182 0 : if (!m_bNeedErrorOnCurrent)
183 0 : return 1L;
184 :
185 0 : m_bNeedErrorOnCurrent = false; // will be reset in OnValueModified
186 :
187 0 : OUString sName;
188 : try
189 : {
190 0 : sName = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME));
191 : }
192 0 : catch(Exception&)
193 : {
194 : DBG_UNHANDLED_EXCEPTION();
195 : }
196 :
197 0 : OUString sMessage(ModuleRes(STR_COULD_NOT_CONVERT_PARAM));
198 0 : sMessage = sMessage.replaceAll( "$name$", sName );
199 0 : MessageDialog(NULL, sMessage).Execute();
200 0 : m_pParam->GrabFocus();
201 0 : return 1L;
202 0 : }
203 : }
204 : }
205 :
206 0 : return 0L;
207 : }
208 :
209 0 : IMPL_LINK(OParameterDialog, OnButtonClicked, PushButton*, pButton)
210 : {
211 0 : if (m_pCancelBtn == pButton)
212 : {
213 : // no interpreting of the given values anymore ....
214 0 : m_pParam->SetLoseFocusHdl(Link()); // no direct call from the control anymore ...
215 0 : m_bNeedErrorOnCurrent = false; // in case of any indirect calls -> no error message
216 0 : m_pCancelBtn->SetClickHdl(Link());
217 0 : m_pCancelBtn->Click();
218 : }
219 0 : else if (m_pOKBtn == pButton)
220 : {
221 : // transfer the current values into the Any
222 0 : if (LINK(this, OParameterDialog, OnEntrySelected).Call(m_pAllParams) != 0L)
223 : { // there was an error interpreting the current text
224 0 : m_bNeedErrorOnCurrent = true;
225 : // we're are out of the complex web :) of direct and indirect calls to OnValueLoseFocus now,
226 : // so the next time it is called we need an error message, again ....
227 : // (TODO : there surely are better solutions for this ...)
228 0 : return 1L;
229 : }
230 :
231 0 : if (m_xParams.is())
232 : {
233 : // write the parameters
234 : try
235 : {
236 0 : PropertyValue* pValues = m_aFinalValues.getArray();
237 0 : for (sal_Int32 i = 0, nCount = m_xParams->getCount(); i<nCount; ++i, ++pValues)
238 : {
239 0 : Reference< XPropertySet > xParamAsSet;
240 0 : m_xParams->getByIndex(i) >>= xParamAsSet;
241 :
242 0 : OUString sValue;
243 0 : pValues->Value >>= sValue;
244 0 : pValues->Value <<= OUString( m_aPredicateInput.getPredicateValue( sValue, xParamAsSet, false ) );
245 0 : }
246 : }
247 0 : catch(Exception&)
248 : {
249 : DBG_UNHANDLED_EXCEPTION();
250 : }
251 :
252 : }
253 : // to close the dialog (which is more code than a simple EndDialog)
254 0 : m_pOKBtn->SetClickHdl(Link());
255 0 : m_pOKBtn->Click();
256 : }
257 0 : else if (m_pTravelNext == pButton)
258 : {
259 0 : sal_Int32 nCurrent = m_pAllParams->GetSelectEntryPos();
260 0 : sal_Int32 nCount = m_pAllParams->GetEntryCount();
261 : OSL_ENSURE(static_cast<size_t>(nCount) == m_aVisitedParams.size(), "OParameterDialog::OnButtonClicked : inconsistent lists !");
262 :
263 : // search the next entry in list we haven't visited yet
264 0 : sal_Int32 nNext = (nCurrent + 1) % nCount;
265 0 : while ((nNext != nCurrent) && ( m_aVisitedParams[nNext] & EF_VISITED ))
266 0 : nNext = (nNext + 1) % nCount;
267 :
268 0 : if ( m_aVisitedParams[nNext] & EF_VISITED )
269 : // there is no such "not visited yet" entry -> simpy take the next one
270 0 : nNext = (nCurrent + 1) % nCount;
271 :
272 0 : m_pAllParams->SelectEntryPos(nNext);
273 0 : LINK(this, OParameterDialog, OnEntrySelected).Call(m_pAllParams);
274 0 : m_bNeedErrorOnCurrent = true;
275 : // we're are out of the complex web :) of direct and indirect calls to OnValueLoseFocus now,
276 : // so the next time it is called we need an error message, again ....
277 : // (TODO : there surely are better solutions for this ...)
278 : }
279 :
280 0 : return 0L;
281 : }
282 :
283 0 : IMPL_LINK(OParameterDialog, OnEntrySelected, ListBox*, /*pList*/)
284 : {
285 0 : if (m_aResetVisitFlag.IsActive())
286 : {
287 0 : LINK(this, OParameterDialog, OnVisitedTimeout).Call(&m_aResetVisitFlag);
288 0 : m_aResetVisitFlag.Stop();
289 : }
290 : // save the old values
291 0 : if (m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND)
292 : {
293 : // do the transformation of the current text
294 0 : if (LINK(this, OParameterDialog, OnValueLoseFocus).Call(m_pParam) != 0L)
295 : { // there was an error interpreting the text
296 0 : m_pAllParams->SelectEntryPos(m_nCurrentlySelected);
297 0 : return 1L;
298 : }
299 :
300 0 : m_aFinalValues[m_nCurrentlySelected].Value <<= OUString(m_pParam->GetText());
301 : }
302 :
303 : // initialize the controls with the new values
304 0 : sal_Int32 nSelected = m_pAllParams->GetSelectEntryPos();
305 : OSL_ENSURE(nSelected != LISTBOX_ENTRY_NOTFOUND, "OParameterDialog::OnEntrySelected : no current entry !");
306 :
307 0 : m_pParam->SetText(::comphelper::getString(m_aFinalValues[nSelected].Value));
308 0 : m_nCurrentlySelected = nSelected;
309 :
310 : // with this the value isn't dirty
311 : OSL_ENSURE(static_cast<size_t>(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnEntrySelected : invalid current entry !");
312 0 : m_aVisitedParams[m_nCurrentlySelected] &= ~EF_DIRTY;
313 :
314 0 : m_aResetVisitFlag.SetTimeout(1000);
315 0 : m_aResetVisitFlag.Start();
316 :
317 0 : return 0L;
318 : }
319 :
320 0 : IMPL_LINK(OParameterDialog, OnVisitedTimeout, Timer*, /*pTimer*/)
321 : {
322 : OSL_ENSURE(m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND, "OParameterDialog::OnVisitedTimeout : invalid call !");
323 :
324 : // mark the currently selected entry as visited
325 : OSL_ENSURE(static_cast<size_t>(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnVisitedTimeout : invalid entry !");
326 0 : m_aVisitedParams[m_nCurrentlySelected] |= EF_VISITED;
327 :
328 : // was it the last "not visited yet" entry ?
329 0 : ByteVector::const_iterator aIter;
330 0 : for ( aIter = m_aVisitedParams.begin();
331 0 : aIter < m_aVisitedParams.end();
332 : ++aIter
333 : )
334 : {
335 0 : if (((*aIter) & EF_VISITED) == 0)
336 0 : break;
337 : }
338 0 : if (aIter == m_aVisitedParams.end())
339 : { // yes, there isn't another one -> change the "default button"
340 0 : m_pTravelNext->SetStyle(m_pTravelNext->GetStyle() & ~WB_DEFBUTTON);
341 0 : m_pOKBtn->SetStyle(m_pOKBtn->GetStyle() | WB_DEFBUTTON);
342 :
343 : // set to focus to one of the buttons temporary (with this their "default"-state is really updated)
344 0 : vcl::Window* pOldFocus = Application::GetFocusWindow();
345 :
346 : // if the old focus window is the value edit do some preparations ...
347 0 : Selection aSel;
348 0 : if (pOldFocus == m_pParam)
349 : {
350 0 : m_pParam->SetLoseFocusHdl(Link());
351 0 : aSel = m_pParam->GetSelection();
352 : }
353 0 : m_pTravelNext->GrabFocus();
354 0 : if (pOldFocus)
355 0 : pOldFocus->GrabFocus();
356 :
357 : // restore the settings for the value edit
358 0 : if (pOldFocus == m_pParam)
359 : {
360 0 : m_pParam->SetLoseFocusHdl(LINK(this, OParameterDialog, OnValueLoseFocus));
361 0 : m_pParam->SetSelection(aSel);
362 : }
363 : }
364 :
365 0 : return 0L;
366 : }
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 72 : } // namespace dbaui
380 :
381 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|