1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_svx.hxx" 26 27 #include "tabwin.hxx" 28 #include "svx/fmtools.hxx" 29 #include "fmservs.hxx" 30 #include "stringlistresource.hxx" 31 32 #include <svx/svxids.hrc> 33 #include <svx/dbaexchange.hxx> 34 #include <com/sun/star/sdb/CommandType.hpp> 35 #include <com/sun/star/sdbcx/XTablesSupplier.hpp> 36 #include <com/sun/star/sdb/XQueriesSupplier.hpp> 37 #include <com/sun/star/sdbc/XPreparedStatement.hpp> 38 #include <com/sun/star/awt/XControlContainer.hpp> 39 #include <com/sun/star/util/XLocalizedAliases.hpp> 40 #include <comphelper/processfactory.hxx> 41 #include <comphelper/stl_types.hxx> 42 43 #ifndef _SVX_FMHELP_HRC 44 #include "fmhelp.hrc" 45 #endif 46 #include <svx/fmshell.hxx> 47 #include "fmshimp.hxx" 48 #include "svx/dbtoolsclient.hxx" 49 #include <svx/fmpage.hxx> 50 51 #ifndef _SVX_FMPGEIMP_HXX 52 #include "fmpgeimp.hxx" 53 #endif 54 55 #ifndef _SVX_FMPROP_HRC 56 #include "fmprop.hrc" 57 #endif 58 59 #ifndef _SVX_FMRESIDS_HRC 60 #include "svx/fmresids.hrc" 61 #endif 62 #include <svx/dialmgr.hxx> 63 #include <tools/shl.hxx> 64 #include <svx/svdpagv.hxx> 65 #include <sfx2/objitem.hxx> 66 #include <sfx2/dispatch.hxx> 67 #include <comphelper/property.hxx> 68 #include <sfx2/frame.hxx> 69 #include <svx/dataaccessdescriptor.hxx> 70 71 const long STD_WIN_POS_X = 50; 72 const long STD_WIN_POS_Y = 50; 73 74 const long STD_WIN_SIZE_X = 120; 75 const long STD_WIN_SIZE_Y = 150; 76 77 const long MIN_WIN_SIZE_X = 50; 78 const long MIN_WIN_SIZE_Y = 50; 79 80 const long LISTBOX_BORDER = 2; 81 82 using namespace ::com::sun::star::sdbc; 83 using namespace ::com::sun::star::sdb; 84 using namespace ::com::sun::star::uno; 85 using namespace ::com::sun::star::datatransfer; 86 using namespace ::com::sun::star::beans; 87 using namespace ::com::sun::star::lang; 88 using namespace ::com::sun::star::form; 89 using namespace ::com::sun::star::container; 90 using namespace ::com::sun::star; 91 using namespace ::svxform; 92 using namespace ::svx; 93 94 95 struct ColumnInfo 96 { 97 ::rtl::OUString sColumnName; 98 ::rtl::OUString sLabel; 99 bool bColumn; 100 ColumnInfo(const ::rtl::OUString& i_sColumnName,const ::rtl::OUString& i_sLabel) 101 : sColumnName(i_sColumnName) 102 , sLabel(i_sLabel) 103 , bColumn(true) 104 { 105 } 106 ColumnInfo(const ::rtl::OUString& i_sColumnName) 107 : sColumnName(i_sColumnName) 108 , bColumn(false) 109 { 110 } 111 }; 112 113 void lcl_addToList( SvTreeListBox& _rListBox, const uno::Reference< container::XNameAccess>& i_xColumns ) 114 { 115 uno::Sequence< ::rtl::OUString > aEntries = i_xColumns->getElementNames(); 116 const ::rtl::OUString* pEntries = aEntries.getConstArray(); 117 sal_Int32 nEntries = aEntries.getLength(); 118 for ( sal_Int32 i = 0; i < nEntries; ++i, ++pEntries ) 119 { 120 uno::Reference< beans::XPropertySet> xColumn(i_xColumns->getByName(*pEntries),UNO_QUERY_THROW); 121 ::rtl::OUString sLabel; 122 if ( xColumn->getPropertySetInfo()->hasPropertyByName(FM_PROP_LABEL) ) 123 xColumn->getPropertyValue(FM_PROP_LABEL) >>= sLabel; 124 if ( sLabel.getLength() ) 125 _rListBox.InsertEntry( sLabel,NULL,sal_False,LIST_APPEND,new ColumnInfo(*pEntries,sLabel) ); 126 else 127 _rListBox.InsertEntry( *pEntries,NULL,sal_False,LIST_APPEND,new ColumnInfo(*pEntries,sLabel) ); 128 } 129 } 130 //================================================================== 131 // class FmFieldWinListBox 132 //================================================================== 133 DBG_NAME(FmFieldWinListBox) 134 //------------------------------------------------------------------------------ 135 FmFieldWinListBox::FmFieldWinListBox( FmFieldWin* pParent ) 136 :SvTreeListBox( pParent, WB_HASBUTTONS|WB_BORDER ) 137 ,pTabWin( pParent ) 138 { 139 DBG_CTOR(FmFieldWinListBox,NULL); 140 SetHelpId( HID_FIELD_SEL ); 141 142 SetHighlightRange( ); 143 } 144 145 //------------------------------------------------------------------------------ 146 FmFieldWinListBox::~FmFieldWinListBox() 147 { 148 DBG_DTOR(FmFieldWinListBox,NULL); 149 } 150 151 //------------------------------------------------------------------------------ 152 sal_Int8 FmFieldWinListBox::AcceptDrop( const AcceptDropEvent& /*rEvt*/ ) 153 { 154 return DND_ACTION_NONE; 155 } 156 157 //------------------------------------------------------------------------------ 158 sal_Int8 FmFieldWinListBox::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ ) 159 { 160 return DND_ACTION_NONE; 161 } 162 163 //------------------------------------------------------------------------------ 164 sal_Bool FmFieldWinListBox::DoubleClickHdl() 165 { 166 if ( pTabWin->createSelectionControls() ) 167 return sal_True; 168 169 return SvTreeListBox::DoubleClickHdl(); 170 } 171 172 //------------------------------------------------------------------------------ 173 void FmFieldWinListBox::StartDrag( sal_Int8 /*_nAction*/, const Point& /*_rPosPixel*/ ) 174 { 175 SvLBoxEntry* pSelected = FirstSelected(); 176 if (!pSelected) 177 // no drag without a field 178 return; 179 180 ::svx::ODataAccessDescriptor aDescriptor; 181 aDescriptor[ daDataSource ] <<= pTabWin->GetDatabaseName(); 182 aDescriptor[ daConnection ] <<= pTabWin->GetConnection().getTyped(); 183 aDescriptor[ daCommand ] <<= pTabWin->GetObjectName(); 184 aDescriptor[ daCommandType ]<<= pTabWin->GetObjectType(); 185 ColumnInfo* pInfo = static_cast<ColumnInfo*>(pSelected->GetUserData()); 186 aDescriptor[ daColumnName ] <<= pInfo->sColumnName; 187 188 TransferableHelper* pTransferColumn = new OColumnTransferable( 189 aDescriptor, CTF_FIELD_DESCRIPTOR | CTF_CONTROL_EXCHANGE | CTF_COLUMN_DESCRIPTOR 190 ); 191 Reference< XTransferable> xEnsureDelete = pTransferColumn; 192 if (pTransferColumn) 193 { 194 EndSelection(); 195 pTransferColumn->StartDrag( this, DND_ACTION_COPY ); 196 } 197 } 198 199 //======================================================================== 200 // class FmFieldWinData 201 //======================================================================== 202 DBG_NAME(FmFieldWinData); 203 //----------------------------------------------------------------------- 204 FmFieldWinData::FmFieldWinData() 205 { 206 DBG_CTOR(FmFieldWinData,NULL); 207 } 208 209 //----------------------------------------------------------------------- 210 FmFieldWinData::~FmFieldWinData() 211 { 212 DBG_DTOR(FmFieldWinData,NULL); 213 } 214 215 //======================================================================== 216 // class FmFieldWin 217 //======================================================================== 218 DBG_NAME(FmFieldWin); 219 //----------------------------------------------------------------------- 220 FmFieldWin::FmFieldWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr, Window* _pParent) 221 :SfxFloatingWindow(_pBindings, _pMgr, _pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE)) 222 ,SfxControllerItem(SID_FM_FIELDS_CONTROL, *_pBindings) 223 ,::comphelper::OPropertyChangeListener(m_aMutex) 224 ,pData(new FmFieldWinData) 225 ,m_nObjectType(0) 226 ,m_pChangeListener(NULL) 227 { 228 DBG_CTOR(FmFieldWin,NULL); 229 SetHelpId( HID_FIELD_SEL_WIN ); 230 231 SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor()) ); 232 pListBox = new FmFieldWinListBox( this ); 233 pListBox->Show(); 234 UpdateContent(NULL); 235 SetSizePixel(Size(STD_WIN_SIZE_X,STD_WIN_SIZE_Y)); 236 } 237 238 //----------------------------------------------------------------------- 239 FmFieldWin::~FmFieldWin() 240 { 241 if (m_pChangeListener) 242 { 243 m_pChangeListener->dispose(); 244 m_pChangeListener->release(); 245 // delete m_pChangeListener; 246 } 247 delete pListBox; 248 delete pData; 249 DBG_DTOR(FmFieldWin,NULL); 250 } 251 252 //----------------------------------------------------------------------- 253 void FmFieldWin::GetFocus() 254 { 255 if ( pListBox ) 256 pListBox->GrabFocus(); 257 else 258 SfxFloatingWindow::GetFocus(); 259 } 260 261 //----------------------------------------------------------------------- 262 sal_Bool FmFieldWin::createSelectionControls( ) 263 { 264 SvLBoxEntry* pSelected = pListBox->FirstSelected(); 265 if ( pSelected ) 266 { 267 // build a descriptor for the currently selected field 268 ODataAccessDescriptor aDescr; 269 aDescr.setDataSource(GetDatabaseName()); 270 271 aDescr[ daConnection ] <<= GetConnection().getTyped(); 272 273 aDescr[ daCommand ] <<= GetObjectName(); 274 aDescr[ daCommandType ] <<= GetObjectType(); 275 ColumnInfo* pInfo = static_cast<ColumnInfo*>(pSelected->GetUserData()); 276 aDescr[ daColumnName ] <<= pInfo->sColumnName;//::rtl::OUString( pListBox->GetEntryText( pSelected) ); 277 278 // transfer this to the SFX world 279 SfxUnoAnyItem aDescriptorItem( SID_FM_DATACCESS_DESCRIPTOR, makeAny( aDescr.createPropertyValueSequence() ) ); 280 const SfxPoolItem* pArgs[] = 281 { 282 &aDescriptorItem, NULL 283 }; 284 285 // execute the create slot 286 GetBindings().Execute( SID_FM_CREATE_FIELDCONTROL, pArgs ); 287 } 288 289 return NULL != pSelected; 290 } 291 292 //----------------------------------------------------------------------- 293 long FmFieldWin::PreNotify( NotifyEvent& _rNEvt ) 294 { 295 if ( EVENT_KEYINPUT == _rNEvt.GetType() ) 296 { 297 const KeyCode& rKeyCode = _rNEvt.GetKeyEvent()->GetKeyCode(); 298 if ( ( 0 == rKeyCode.GetModifier() ) && ( KEY_RETURN == rKeyCode.GetCode() ) ) 299 { 300 if ( createSelectionControls() ) 301 return 1; 302 } 303 } 304 305 return SfxFloatingWindow::PreNotify( _rNEvt ); 306 } 307 308 //----------------------------------------------------------------------- 309 sal_Bool FmFieldWin::Close() 310 { 311 return SfxFloatingWindow::Close(); 312 } 313 314 //----------------------------------------------------------------------- 315 void FmFieldWin::_propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw( ::com::sun::star::uno::RuntimeException ) 316 { 317 ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xForm(evt.Source, ::com::sun::star::uno::UNO_QUERY); 318 UpdateContent(xForm); 319 } 320 321 //----------------------------------------------------------------------- 322 void FmFieldWin::StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState) 323 { 324 if (!pState || SID_FM_FIELDS_CONTROL != nSID) 325 return; 326 327 if (eState >= SFX_ITEM_AVAILABLE) 328 { 329 FmFormShell* pShell = PTR_CAST(FmFormShell,((SfxObjectItem*)pState)->GetShell()); 330 UpdateContent(pShell); 331 } 332 else 333 UpdateContent(NULL); 334 } 335 336 //----------------------------------------------------------------------- 337 void FmFieldWin::UpdateContent(FmFormShell* pShell) 338 { 339 pListBox->Clear(); 340 String aTitle( SVX_RES( RID_STR_FIELDSELECTION ) ); 341 SetText( aTitle ); 342 343 if (!pShell || !pShell->GetImpl()) 344 return; 345 346 Reference< XForm > xForm = pShell->GetImpl()->getCurrentForm(); 347 if ( xForm.is() ) 348 UpdateContent( xForm ); 349 } 350 351 //----------------------------------------------------------------------- 352 void FmFieldWin::UpdateContent(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > & xForm) 353 { 354 try 355 { 356 // ListBox loeschen 357 pListBox->Clear(); 358 UniString aTitle(SVX_RES(RID_STR_FIELDSELECTION)); 359 SetText(aTitle); 360 361 if (!xForm.is()) 362 return; 363 364 Reference< XPreparedStatement > xStatement; 365 Reference< XPropertySet > xSet(xForm, UNO_QUERY); 366 367 m_aObjectName = ::comphelper::getString(xSet->getPropertyValue(FM_PROP_COMMAND)); 368 m_aDatabaseName = ::comphelper::getString(xSet->getPropertyValue(FM_PROP_DATASOURCE)); 369 m_nObjectType = ::comphelper::getINT32(xSet->getPropertyValue(FM_PROP_COMMANDTYPE)); 370 371 // get the connection of the form 372 OStaticDataAccessTools aTools; 373 m_aConnection.reset( 374 aTools.connectRowset( Reference< XRowSet >( xForm, UNO_QUERY ), ::comphelper::getProcessServiceFactory(), sal_True ), 375 SharedConnection::NoTakeOwnership 376 ); 377 // TODO: When incompatible changes (such as extending the "virtualdbtools" interface by ensureRowSetConnection) 378 // are allowed, again, we should change this: dbtools should consistently use SharedConnection all over 379 // the place, and connectRowset should be replaced with ensureRowSetConnection 380 381 // get the fields of the object 382 383 if ( m_aConnection.is() && m_aObjectName.getLength() ) 384 { 385 Reference< XComponent > xKeepFieldsAlive; 386 Reference< XNameAccess > xColumns = getFieldsByCommandDescriptor( m_aConnection, m_nObjectType, m_aObjectName,xKeepFieldsAlive ); 387 if ( xColumns.is() ) 388 lcl_addToList(*pListBox,xColumns); 389 } 390 391 // Prefix setzen 392 UniString aPrefix; 393 StringListResource aPrefixes( SVX_RES( RID_RSC_TABWIN_PREFIX ) ); 394 395 switch (m_nObjectType) 396 { 397 case CommandType::TABLE: 398 aPrefix = aPrefixes[0]; 399 break; 400 case CommandType::QUERY: 401 aPrefix = aPrefixes[1]; 402 break; 403 default: 404 aPrefix = aPrefixes[2]; 405 break; 406 } 407 408 // an dem PropertySet nach Aenderungen der ControlSource lauschen 409 if (m_pChangeListener) 410 { 411 m_pChangeListener->dispose(); 412 m_pChangeListener->release(); 413 } 414 m_pChangeListener = new ::comphelper::OPropertyChangeMultiplexer(this, xSet); 415 m_pChangeListener->acquire(); 416 m_pChangeListener->addProperty(FM_PROP_DATASOURCE); 417 m_pChangeListener->addProperty(FM_PROP_COMMAND); 418 m_pChangeListener->addProperty(FM_PROP_COMMANDTYPE); 419 420 // Titel setzen 421 aTitle.AppendAscii(" "); 422 aTitle += aPrefix; 423 aTitle.AppendAscii(" "); 424 aTitle += m_aObjectName.getStr(); 425 SetText( aTitle ); 426 } 427 catch( const Exception& ) 428 { 429 DBG_ERROR( "FmTabWin::UpdateContent: caught an exception!" ); 430 } 431 } 432 433 //----------------------------------------------------------------------- 434 void FmFieldWin::Resize() 435 { 436 SfxFloatingWindow::Resize(); 437 438 Point aPos(GetPosPixel()); 439 Size aOutputSize( GetOutputSizePixel() ); 440 441 ////////////////////////////////////////////////////////////////////// 442 443 // Groesse der ::com::sun::star::form::ListBox anpassen 444 Point aLBPos( LISTBOX_BORDER, LISTBOX_BORDER ); 445 Size aLBSize( aOutputSize ); 446 aLBSize.Width() -= (2*LISTBOX_BORDER); 447 aLBSize.Height() -= (2*LISTBOX_BORDER); 448 449 pListBox->SetPosSizePixel( aLBPos, aLBSize ); 450 } 451 452 //----------------------------------------------------------------------- 453 void FmFieldWin::FillInfo( SfxChildWinInfo& rInfo ) const 454 { 455 rInfo.bVisible = sal_False; 456 } 457 458 //----------------------------------------------------------------------- 459 SFX_IMPL_FLOATINGWINDOW(FmFieldWinMgr, SID_FM_ADD_FIELD) 460 461 //----------------------------------------------------------------------- 462 FmFieldWinMgr::FmFieldWinMgr(Window* _pParent, sal_uInt16 _nId, 463 SfxBindings* _pBindings, SfxChildWinInfo* _pInfo) 464 :SfxChildWindow(_pParent, _nId) 465 { 466 pWindow = new FmFieldWin(_pBindings, this, _pParent); 467 SetHideNotDelete(sal_True); 468 eChildAlignment = SFX_ALIGN_NOALIGNMENT; 469 ((SfxFloatingWindow*)pWindow)->Initialize( _pInfo ); 470 } 471 472 473