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 <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 <tools/diagnose_ex.h> 31 32 namespace dbaui 33 { 34 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; 42 43 // OParameterDialog 44 45 OParameterDialog(weld::Window * pParent,const Reference<XIndexAccess> & rParamContainer,const Reference<XConnection> & _rxConnection,const Reference<XComponentContext> & rxContext)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_xAllParams(m_xBuilder->weld_tree_view("allParamTreeview")) 54 , m_xParam(m_xBuilder->weld_entry("paramEntry")) 55 , m_xTravelNext(m_xBuilder->weld_button("next")) 56 , m_xOKBtn(m_xBuilder->weld_button("ok")) 57 , m_xCancelBtn(m_xBuilder->weld_button("cancel")) 58 { 59 m_xAllParams->set_size_request(-1, m_xAllParams->get_height_rows(10)); 60 61 if (rxContext.is()) 62 m_xFormatter.set( NumberFormatter::create( rxContext ), UNO_QUERY_THROW); 63 else { 64 OSL_FAIL("OParameterDialog::OParameterDialog: need a service factory!"); 65 } 66 67 Reference< XNumberFormatsSupplier > xNumberFormats = ::dbtools::getNumberFormats(m_xConnection, true); 68 if (!xNumberFormats.is()) 69 ::comphelper::disposeComponent(m_xFormatter); 70 else 71 m_xFormatter->attachNumberFormatsSupplier(xNumberFormats); 72 try 73 { 74 OSL_ENSURE(rParamContainer->getCount(), "OParameterDialog::OParameterDialog : can't handle empty containers !"); 75 76 m_aFinalValues.realloc(rParamContainer->getCount()); 77 PropertyValue* pValues = m_aFinalValues.getArray(); 78 79 for (sal_Int32 i = 0, nCount = rParamContainer->getCount(); i<nCount; ++i, ++pValues) 80 { 81 Reference< XPropertySet > xParamAsSet; 82 rParamContainer->getByIndex(i) >>= xParamAsSet; 83 OSL_ENSURE(xParamAsSet.is(),"Parameter is null!"); 84 if(!xParamAsSet.is()) 85 continue; 86 pValues->Name = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME)); 87 m_xAllParams->append_text(pValues->Name); 88 89 m_aVisitedParams.push_back(VisitFlags::NONE); 90 // not visited, not dirty 91 } 92 93 m_xParams = rParamContainer; 94 } 95 catch(Exception&) 96 { 97 DBG_UNHANDLED_EXCEPTION("dbaccess"); 98 } 99 100 Construct(); 101 102 m_aResetVisitFlag.SetInvokeHandler(LINK(this, OParameterDialog, OnVisitedTimeout)); 103 } 104 ~OParameterDialog()105 OParameterDialog::~OParameterDialog() 106 { 107 if (m_aResetVisitFlag.IsActive()) 108 m_aResetVisitFlag.Stop(); 109 } 110 Construct()111 void OParameterDialog::Construct() 112 { 113 m_xAllParams->connect_changed(LINK(this, OParameterDialog, OnEntryListBoxSelected)); 114 m_xParam->connect_focus_out(LINK(this, OParameterDialog, OnValueLoseFocusHdl)); 115 m_xParam->connect_changed(LINK(this, OParameterDialog, OnValueModified)); 116 m_xTravelNext->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked)); 117 m_xOKBtn->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked)); 118 m_xCancelBtn->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked)); 119 120 if (m_xAllParams->n_children()) 121 { 122 m_xAllParams->select(0); 123 OnEntrySelected(); 124 125 if (m_xAllParams->n_children() == 1) 126 { 127 m_xTravelNext->set_sensitive(false); 128 } 129 130 if (m_xAllParams->n_children() > 1) 131 { 132 m_xOKBtn->set_has_default(false); 133 m_xTravelNext->set_has_default(true); 134 } 135 } 136 137 m_xParam->grab_focus(); 138 } 139 IMPL_LINK_NOARG(OParameterDialog,OnValueLoseFocusHdl,weld::Widget &,void)140 IMPL_LINK_NOARG(OParameterDialog, OnValueLoseFocusHdl, weld::Widget&, void) 141 { 142 CheckValueForError(); 143 } 144 CheckValueForError()145 bool OParameterDialog::CheckValueForError() 146 { 147 if (m_nCurrentlySelected != -1) 148 { 149 if ( !( m_aVisitedParams[ m_nCurrentlySelected ] & VisitFlags::Dirty ) ) 150 // nothing to do, the value isn't dirty 151 return false; 152 } 153 154 bool bRet = false; 155 156 Reference< XPropertySet > xParamAsSet; 157 m_xParams->getByIndex(m_nCurrentlySelected) >>= xParamAsSet; 158 if (xParamAsSet.is()) 159 { 160 if (m_xConnection.is() && m_xFormatter.is()) 161 { 162 OUString sParamValue(m_xParam->get_text()); 163 bool bValid = m_aPredicateInput.normalizePredicateString( sParamValue, xParamAsSet ); 164 m_xParam->set_text(sParamValue); 165 m_xParam->set_message_type(bValid ? weld::EntryMessageType::Normal : weld::EntryMessageType::Error); 166 OUString sToolTip; 167 if ( bValid ) 168 { 169 // with this the value isn't dirty anymore 170 if (m_nCurrentlySelected != -1) 171 m_aVisitedParams[m_nCurrentlySelected] &= ~VisitFlags::Dirty; 172 } 173 else 174 { 175 OUString sName; 176 try 177 { 178 sName = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME)); 179 } 180 catch(Exception&) 181 { 182 DBG_UNHANDLED_EXCEPTION("dbaccess"); 183 } 184 185 OUString sMessage(DBA_RES(STR_COULD_NOT_CONVERT_PARAM)); 186 sToolTip = sMessage.replaceAll( "$name$", sName ); 187 m_xParam->grab_focus(); 188 bRet = true; 189 } 190 m_xParam->set_tooltip_text(sToolTip); 191 m_xOKBtn->set_sensitive(bValid); 192 } 193 } 194 195 return bRet; 196 } 197 IMPL_LINK(OParameterDialog,OnButtonClicked,weld::Button &,rButton,void)198 IMPL_LINK(OParameterDialog, OnButtonClicked, weld::Button&, rButton, void) 199 { 200 if (m_xCancelBtn.get() == &rButton) 201 { 202 // no interpreting of the given values anymore... 203 m_xParam->connect_focus_out(Link<weld::Widget&, void>()); // no direct call from the control anymore ... 204 m_xDialog->response(RET_CANCEL); 205 } 206 else if (m_xOKBtn.get() == &rButton) 207 { 208 // transfer the current values into the Any 209 if (OnEntrySelected()) 210 { // there was an error interpreting the current text 211 return; 212 } 213 214 if (m_xParams.is()) 215 { 216 // write the parameters 217 try 218 { 219 PropertyValue* pValues = m_aFinalValues.getArray(); 220 for (sal_Int32 i = 0, nCount = m_xParams->getCount(); i<nCount; ++i, ++pValues) 221 { 222 Reference< XPropertySet > xParamAsSet; 223 m_xParams->getByIndex(i) >>= xParamAsSet; 224 225 OUString sValue; 226 pValues->Value >>= sValue; 227 pValues->Value = m_aPredicateInput.getPredicateValue( sValue, xParamAsSet ); 228 } 229 } 230 catch(Exception&) 231 { 232 DBG_UNHANDLED_EXCEPTION("dbaccess"); 233 } 234 235 } 236 m_xDialog->response(RET_OK); 237 } 238 else if (m_xTravelNext.get() == &rButton) 239 { 240 if (sal_Int32 nCount = m_xAllParams->n_children()) 241 { 242 sal_Int32 nCurrent = m_xAllParams->get_selected_index(); 243 OSL_ENSURE(static_cast<size_t>(nCount) == m_aVisitedParams.size(), "OParameterDialog::OnButtonClicked : inconsistent lists !"); 244 245 // search the next entry in list we haven't visited yet 246 sal_Int32 nNext = (nCurrent + 1) % nCount; 247 while ((nNext != nCurrent) && ( m_aVisitedParams[nNext] & VisitFlags::Visited )) 248 nNext = (nNext + 1) % nCount; 249 250 if ( m_aVisitedParams[nNext] & VisitFlags::Visited ) 251 // there is no such "not visited yet" entry -> simply take the next one 252 nNext = (nCurrent + 1) % nCount; 253 254 m_xAllParams->select(nNext); 255 OnEntrySelected(); 256 } 257 } 258 } 259 IMPL_LINK_NOARG(OParameterDialog,OnEntryListBoxSelected,weld::TreeView &,void)260 IMPL_LINK_NOARG(OParameterDialog, OnEntryListBoxSelected, weld::TreeView&, void) 261 { 262 OnEntrySelected(); 263 } 264 OnEntrySelected()265 bool OParameterDialog::OnEntrySelected() 266 { 267 if (m_aResetVisitFlag.IsActive()) 268 { 269 LINK(this, OParameterDialog, OnVisitedTimeout).Call(&m_aResetVisitFlag); 270 m_aResetVisitFlag.Stop(); 271 } 272 // save the old values 273 if (m_nCurrentlySelected != -1) 274 { 275 // do the transformation of the current text 276 if (CheckValueForError()) 277 { // there was an error interpreting the text 278 m_xAllParams->select(m_nCurrentlySelected); 279 return true; 280 } 281 282 m_aFinalValues[m_nCurrentlySelected].Value <<= m_xParam->get_text(); 283 } 284 285 // initialize the controls with the new values 286 sal_Int32 nSelected = m_xAllParams->get_selected_index(); 287 OSL_ENSURE(nSelected != -1, "OParameterDialog::OnEntrySelected : no current entry !"); 288 289 m_xParam->set_text(::comphelper::getString(m_aFinalValues[nSelected].Value)); 290 m_nCurrentlySelected = nSelected; 291 292 // with this the value isn't dirty 293 OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnEntrySelected : invalid current entry !"); 294 m_aVisitedParams[m_nCurrentlySelected] &= ~VisitFlags::Dirty; 295 296 m_aResetVisitFlag.SetTimeout(1000); 297 m_aResetVisitFlag.Start(); 298 299 return false; 300 } 301 IMPL_LINK_NOARG(OParameterDialog,OnVisitedTimeout,Timer *,void)302 IMPL_LINK_NOARG(OParameterDialog, OnVisitedTimeout, Timer*, void) 303 { 304 OSL_ENSURE(m_nCurrentlySelected != -1, "OParameterDialog::OnVisitedTimeout : invalid call !"); 305 306 // mark the currently selected entry as visited 307 OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnVisitedTimeout : invalid entry !"); 308 m_aVisitedParams[m_nCurrentlySelected] |= VisitFlags::Visited; 309 310 // was it the last "not visited yet" entry ? 311 bool bVisited = false; 312 for (auto const& visitedParam : m_aVisitedParams) 313 { 314 if (!(visitedParam & VisitFlags::Visited)) 315 { 316 bVisited = true; 317 break; 318 } 319 } 320 321 if (!bVisited) 322 { 323 // yes, there isn't another one -> change the "default button" 324 m_xTravelNext->set_has_default(false); 325 m_xOKBtn->set_has_default(true); 326 } 327 } 328 IMPL_LINK(OParameterDialog,OnValueModified,weld::Entry &,rEdit,void)329 IMPL_LINK(OParameterDialog, OnValueModified, weld::Entry&, rEdit, void) 330 { 331 // mark the currently selected entry as dirty 332 OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnValueModified : invalid entry !"); 333 m_aVisitedParams[m_nCurrentlySelected] |= VisitFlags::Dirty; 334 rEdit.set_message_type(weld::EntryMessageType::Normal); 335 } 336 337 } // namespace dbaui 338 339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 340