xref: /trunk/main/dbaccess/source/ui/dlg/paramdialog.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
30 
31 #ifndef _DBAUI_PARAMDIALOG_HXX_
32 #include "paramdialog.hxx"
33 #endif
34 #ifndef _DBAUI_PARAMDIALOG_HRC_
35 #include "paramdialog.hrc"
36 #endif
37 #ifndef _DBU_DLG_HRC_
38 #include "dbu_dlg.hrc"
39 #endif
40 #ifndef _DBAUI_COMMON_TYPES_HXX_
41 #include "commontypes.hxx"
42 #endif
43 #ifndef _DBAUI_MODULE_DBU_HXX_
44 #include "moduledbu.hxx"
45 #endif
46 #ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTER_HPP_
47 #include <com/sun/star/util/XNumberFormatter.hpp>
48 #endif
49 #ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_
50 #include <com/sun/star/sdbc/DataType.hpp>
51 #endif
52 #ifndef _CONNECTIVITY_DBTOOLS_HXX_
53 #include <connectivity/dbtools.hxx>
54 #endif
55 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
56 #include "dbustrings.hrc"
57 #endif
58 #ifndef _SV_SVAPP_HXX
59 #include <vcl/svapp.hxx>
60 #endif
61 #ifndef _SV_MSGBOX_HXX
62 #include <vcl/msgbox.hxx>
63 #endif
64 #ifndef _TOOLS_DEBUG_HXX
65 #include <tools/debug.hxx>
66 #endif
67 #include <tools/diagnose_ex.h>
68 #ifndef _DBAUI_LOCALRESACCESS_HXX_
69 #include "localresaccess.hxx"
70 #endif
71 #ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX
72 #include <unotools/syslocale.hxx>
73 #endif
74 
75 #define EF_VISITED      0x0001
76 #define EF_DIRTY        0x0002
77 
78 //.........................................................................
79 namespace dbaui
80 {
81 //.........................................................................
82 
83     using namespace ::com::sun::star::uno;
84     using namespace ::com::sun::star::lang;
85     using namespace ::com::sun::star::beans;
86     using namespace ::com::sun::star::container;
87     using namespace ::com::sun::star::sdbc;
88     using namespace ::com::sun::star::util;
89     using namespace ::connectivity;
90 
91     //==================================================================
92     //= OParameterDialog
93     //==================================================================
94 
95     //------------------------------------------------------------------------------
96     #define INIT_MEMBERS()                                          \
97         :ModalDialog( pParent, ModuleRes(DLG_PARAMETERS))           \
98         ,m_aNamesFrame  (this, ModuleRes(FL_PARAMS))                    \
99         ,m_aAllParams   (this, ModuleRes(LB_ALLPARAMS))                 \
100         ,m_aValueFrame  (this, ModuleRes(FT_VALUE))                     \
101         ,m_aParam       (this, ModuleRes(ET_PARAM))                     \
102         ,m_aTravelNext  (this, ModuleRes(BT_TRAVELNEXT))                \
103         ,m_aOKBtn       (this, ModuleRes(BT_OK))                        \
104         ,m_aCancelBtn   (this, ModuleRes(BT_CANCEL))                    \
105         ,m_nCurrentlySelected(LISTBOX_ENTRY_NOTFOUND)               \
106         ,m_xConnection(_rxConnection)                               \
107         ,m_aPredicateInput( _rxORB, _rxConnection, getParseContext() )  \
108         ,m_bNeedErrorOnCurrent(sal_True)                            \
109 
110 
111     //------------------------------------------------------------------------------
112 DBG_NAME(OParameterDialog)
113 
114     OParameterDialog::OParameterDialog(
115             Window* pParent, const Reference< XIndexAccess > & rParamContainer,
116             const Reference< XConnection > & _rxConnection, const Reference< XMultiServiceFactory >& _rxORB)
117         INIT_MEMBERS()
118     {
119         DBG_CTOR(OParameterDialog,NULL);
120 
121         if (_rxORB.is())
122             m_xFormatter = Reference< XNumberFormatter>(_rxORB->createInstance(
123             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.NumberFormatter"))), UNO_QUERY);
124         else {
125             DBG_ERROR("OParameterDialog::OParameterDialog: need a service factory!");
126         }
127 
128         Reference< XNumberFormatsSupplier >  xNumberFormats = ::dbtools::getNumberFormats(m_xConnection, sal_True);
129         if (!xNumberFormats.is())
130             ::comphelper::disposeComponent(m_xFormatter);
131         else if (m_xFormatter.is())
132             m_xFormatter->attachNumberFormatsSupplier(xNumberFormats);
133         try
134         {
135             DBG_ASSERT(rParamContainer->getCount(), "OParameterDialog::OParameterDialog : can't handle empty containers !");
136 
137             m_aFinalValues.realloc(rParamContainer->getCount());
138             PropertyValue* pValues = m_aFinalValues.getArray();
139 
140             for (sal_Int32 i = 0, nCount = rParamContainer->getCount(); i<nCount; ++i, ++pValues)
141             {
142                 Reference< XPropertySet >  xParamAsSet;
143                 rParamContainer->getByIndex(i) >>= xParamAsSet;
144                 OSL_ENSURE(xParamAsSet.is(),"Parameter is null!");
145                 if(!xParamAsSet.is())
146                     continue;
147                 pValues->Name = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME));
148                 m_aAllParams.InsertEntry(pValues->Name);
149 
150                 if (!pValues->Value.hasValue())
151                     // it won't have a value, 'cause it's default constructed. But may be later we support
152                     // initializing this dialog with values
153                     pValues->Value = makeAny(::rtl::OUString());
154                     // default the values to an empty string
155 
156                 m_aVisitedParams.push_back(0);
157                     // not visited, not dirty
158             }
159 
160             m_xParams = rParamContainer;
161         }
162         catch(Exception&)
163         {
164             DBG_UNHANDLED_EXCEPTION();
165         }
166 
167 
168         Construct();
169 
170         m_aResetVisitFlag.SetTimeoutHdl(LINK(this, OParameterDialog, OnVisitedTimeout));
171 
172         FreeResource();
173     }
174 
175     //------------------------------------------------------------------------------
176     OParameterDialog::~OParameterDialog()
177     {
178         if (m_aResetVisitFlag.IsActive())
179             m_aResetVisitFlag.Stop();
180 
181         DBG_DTOR(OParameterDialog,NULL);
182     }
183 
184     //------------------------------------------------------------------------------
185     void OParameterDialog::Construct()
186     {
187         m_aAllParams.SetSelectHdl(LINK(this, OParameterDialog, OnEntrySelected));
188         m_aParam.SetLoseFocusHdl(LINK(this, OParameterDialog, OnValueLoseFocus));
189         m_aParam.SetModifyHdl(LINK(this, OParameterDialog, OnValueModified));
190         m_aTravelNext.SetClickHdl(LINK(this, OParameterDialog, OnButtonClicked));
191         m_aOKBtn.SetClickHdl(LINK(this, OParameterDialog, OnButtonClicked));
192         m_aCancelBtn.SetClickHdl(LINK(this, OParameterDialog, OnButtonClicked));
193 
194         if (m_aAllParams.GetEntryCount())
195         {
196             m_aAllParams.SelectEntryPos(0);
197             LINK(this, OParameterDialog, OnEntrySelected).Call(&m_aAllParams);
198 
199             if (m_aAllParams.GetEntryCount() == 1)
200             {
201                 m_aTravelNext.Enable(sal_False);
202             }
203 
204             if (m_aAllParams.GetEntryCount() > 1)
205             {
206                 m_aOKBtn.SetStyle(m_aOKBtn.GetStyle() & ~WB_DEFBUTTON);
207                 m_aTravelNext.SetStyle(m_aTravelNext.GetStyle() | WB_DEFBUTTON);
208             }
209         }
210 
211         m_aParam.GrabFocus();
212     }
213 
214     //------------------------------------------------------------------------------
215     IMPL_LINK(OParameterDialog, OnValueLoseFocus, Control*, /*pSource*/)
216     {
217         if (m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND)
218         {
219             if ( ( m_aVisitedParams[ m_nCurrentlySelected ] & EF_DIRTY ) == 0 )
220                 // nothing to do, the value isn't dirty
221                 return 0L;
222         }
223 
224         // transform the current string according to the param field type
225         ::rtl::OUString sTransformedText(m_aParam.GetText());
226         Reference< XPropertySet >  xParamAsSet;
227         m_xParams->getByIndex(m_nCurrentlySelected) >>= xParamAsSet;
228         if (xParamAsSet.is())
229         {
230             if (m_xConnection.is() && m_xFormatter.is())
231             {
232                 ::rtl::OUString sParamValue( m_aParam.GetText() );
233                 sal_Bool bValid = m_aPredicateInput.normalizePredicateString( sParamValue, xParamAsSet );
234                 m_aParam.SetText( sParamValue );
235                 if ( bValid )
236                 {
237                     // with this the value isn't dirty anymore
238                     if (m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND)
239                         m_aVisitedParams[m_nCurrentlySelected] &= ~EF_DIRTY;
240                 }
241                 else
242                 {
243                     if (!m_bNeedErrorOnCurrent)
244                         return 1L;
245 
246                     m_bNeedErrorOnCurrent = sal_False;  // will be reset in OnValueModified
247 
248                     ::rtl::OUString sName;
249                     try
250                     {
251                         sName = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME));
252                     }
253                     catch(Exception&)
254                     {
255                         DBG_UNHANDLED_EXCEPTION();
256                     }
257 
258                     String sMessage;
259                     {
260                         LocalResourceAccess aDummy(DLG_PARAMETERS, RSC_MODALDIALOG);
261                         sMessage = String(ModuleRes(STR_COULD_NOT_CONVERT_PARAM));
262                     }
263                     sMessage.SearchAndReplaceAll(String::CreateFromAscii("$name$"), sName.getStr());
264                     ErrorBox(NULL, WB_OK, sMessage).Execute();
265                     m_aParam.GrabFocus();
266                     return 1L;
267                 }
268             }
269         }
270 
271         return 0L;
272     }
273 
274     //------------------------------------------------------------------------------
275     IMPL_LINK(OParameterDialog, OnButtonClicked, PushButton*, pButton)
276     {
277         if (&m_aCancelBtn == pButton)
278         {
279             // no interpreting of the given values anymore ....
280             m_aParam.SetLoseFocusHdl(Link());   // no direct call from the control anymore ...
281             m_bNeedErrorOnCurrent = sal_False;      // in case of any indirect calls -> no error message
282             m_aCancelBtn.SetClickHdl(Link());
283             m_aCancelBtn.Click();
284         }
285         else if (&m_aOKBtn == pButton)
286         {
287             // transfer the current values into the Any
288             if (LINK(this, OParameterDialog, OnEntrySelected).Call(&m_aAllParams) != 0L)
289             {   // there was an error interpreting the current text
290                 m_bNeedErrorOnCurrent = sal_True;
291                     // we're are out of the complex web :) of direct and indirect calls to OnValueLoseFocus now,
292                     // so the next time it is called we need an error message, again ....
293                     // (TODO : there surely are better solutions for this ...)
294                 return 1L;
295             }
296 
297             if (m_xParams.is())
298             {
299                 // write the parameters
300                 try
301                 {
302                     ::rtl::OUString sError;
303                     PropertyValue* pValues = m_aFinalValues.getArray();
304                     for (sal_Int32 i = 0, nCount = m_xParams->getCount(); i<nCount; ++i, ++pValues)
305                     {
306                         Reference< XPropertySet >  xParamAsSet;
307                         m_xParams->getByIndex(i) >>= xParamAsSet;
308 
309                         ::rtl::OUString sValue;
310                         pValues->Value >>= sValue;
311                         pValues->Value <<= ::rtl::OUString( m_aPredicateInput.getPredicateValue( sValue, xParamAsSet, sal_False ) );
312                     }
313                 }
314                 catch(Exception&)
315                 {
316                     DBG_UNHANDLED_EXCEPTION();
317                 }
318 
319             }
320             // to close the dialog (which is more code than a simple EndDialog)
321             m_aOKBtn.SetClickHdl(Link());
322             m_aOKBtn.Click();
323         }
324         else if (&m_aTravelNext == pButton)
325         {
326             sal_uInt16 nCurrent = m_aAllParams.GetSelectEntryPos();
327             sal_uInt16 nCount = m_aAllParams.GetEntryCount();
328             DBG_ASSERT(nCount == m_aVisitedParams.size(), "OParameterDialog::OnButtonClicked : inconsistent lists !");
329 
330             // search the next entry in list we haven't visited yet
331             sal_uInt16 nNext = (nCurrent + 1) % nCount;
332             while ((nNext != nCurrent) && ( m_aVisitedParams[nNext] & EF_VISITED ))
333                 nNext = (nNext + 1) % nCount;
334 
335             if ( m_aVisitedParams[nNext] & EF_VISITED )
336                 // there is no such "not visited yet" entry -> simpy take the next one
337                 nNext = (nCurrent + 1) % nCount;
338 
339             m_aAllParams.SelectEntryPos(nNext);
340             LINK(this, OParameterDialog, OnEntrySelected).Call(&m_aAllParams);
341             m_bNeedErrorOnCurrent = sal_True;
342                 // we're are out of the complex web :) of direct and indirect calls to OnValueLoseFocus now,
343                 // so the next time it is called we need an error message, again ....
344                 // (TODO : there surely are better solutions for this ...)
345         }
346 
347         return 0L;
348     }
349 
350     //------------------------------------------------------------------------------
351     IMPL_LINK(OParameterDialog, OnEntrySelected, ListBox*, /*pList*/)
352     {
353         if (m_aResetVisitFlag.IsActive())
354         {
355             LINK(this, OParameterDialog, OnVisitedTimeout).Call(&m_aResetVisitFlag);
356             m_aResetVisitFlag.Stop();
357         }
358         // save the old values
359         if (m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND)
360         {
361             // do the transformation of the current text
362             if (LINK(this, OParameterDialog, OnValueLoseFocus).Call(&m_aParam) != 0L)
363             {   // there was an error interpreting the text
364                 m_aAllParams.SelectEntryPos(m_nCurrentlySelected);
365                 return 1L;
366             }
367 
368             m_aFinalValues[m_nCurrentlySelected].Value <<= ::rtl::OUString(m_aParam.GetText());
369         }
370 
371         // initialize the controls with the new values
372         sal_uInt16 nSelected = m_aAllParams.GetSelectEntryPos();
373         DBG_ASSERT(nSelected != LISTBOX_ENTRY_NOTFOUND, "OParameterDialog::OnEntrySelected : no current entry !");
374 
375         m_aParam.SetText(::comphelper::getString(m_aFinalValues[nSelected].Value));
376         m_nCurrentlySelected = nSelected;
377 
378         // with this the value isn't dirty
379         DBG_ASSERT(m_nCurrentlySelected < m_aVisitedParams.size(), "OParameterDialog::OnEntrySelected : invalid current entry !");
380         m_aVisitedParams[m_nCurrentlySelected] &= ~EF_DIRTY;
381 
382         m_aResetVisitFlag.SetTimeout(1000);
383         m_aResetVisitFlag.Start();
384 
385         return 0L;
386     }
387 
388     //------------------------------------------------------------------------------
389     IMPL_LINK(OParameterDialog, OnVisitedTimeout, Timer*, /*pTimer*/)
390     {
391         DBG_ASSERT(m_nCurrentlySelected != LISTBOX_ENTRY_NOTFOUND, "OParameterDialog::OnVisitedTimeout : invalid call !");
392 
393         // mark the currently selected entry as visited
394         DBG_ASSERT(m_nCurrentlySelected < m_aVisitedParams.size(), "OParameterDialog::OnVisitedTimeout : invalid entry !");
395         m_aVisitedParams[m_nCurrentlySelected] |= EF_VISITED;
396 
397         // was it the last "not visited yet" entry ?
398         ConstByteVectorIterator aIter;
399         for (   aIter = m_aVisitedParams.begin();
400                 aIter < m_aVisitedParams.end();
401                 ++aIter
402             )
403         {
404             if (((*aIter) & EF_VISITED) == 0)
405                 break;
406         }
407         if (aIter == m_aVisitedParams.end())
408         {   // yes, there isn't another one -> change the "default button"
409             m_aTravelNext.SetStyle(m_aTravelNext.GetStyle() & ~WB_DEFBUTTON);
410             m_aOKBtn.SetStyle(m_aOKBtn.GetStyle() | WB_DEFBUTTON);
411 
412             // set to focus to one of the buttons temporary (with this their "default"-state is really updated)
413             Window* pOldFocus = Application::GetFocusWindow();
414 
415             // if the old focus window is the value edit do some preparations ...
416             Selection aSel;
417             if (pOldFocus == &m_aParam)
418             {
419                 m_aParam.SetLoseFocusHdl(Link());
420                 aSel = m_aParam.GetSelection();
421             }
422             m_aTravelNext.GrabFocus();
423             if (pOldFocus)
424                 pOldFocus->GrabFocus();
425 
426             // restore the settings for the value edit
427             if (pOldFocus == &m_aParam)
428             {
429                 m_aParam.SetLoseFocusHdl(LINK(this, OParameterDialog, OnValueLoseFocus));
430                 m_aParam.SetSelection(aSel);
431             }
432         }
433 
434         return 0L;
435     }
436 
437     //------------------------------------------------------------------------------
438     IMPL_LINK(OParameterDialog, OnValueModified, Control*, /*pBox*/)
439     {
440         // mark the currently selected entry as dirty
441         DBG_ASSERT(m_nCurrentlySelected < m_aVisitedParams.size(), "OParameterDialog::OnValueModified : invalid entry !");
442         m_aVisitedParams[m_nCurrentlySelected] |= EF_DIRTY;
443 
444         m_bNeedErrorOnCurrent = sal_True;
445 
446         return 0L;
447     }
448 
449 
450 //.........................................................................
451 }   // namespace dbaui
452 //.........................................................................
453